public void run() {
   DatagramSocket socketCopy = socket;
   if (socketCopy != null) {
     try {
       socketCopy.setSoTimeout(getSocketTimeout());
       if (receiveBufferSize > 0) {
         socketCopy.setReceiveBufferSize(Math.max(receiveBufferSize, maxInboundMessageSize));
       }
       if (logger.isDebugEnabled()) {
         logger.debug(
             "UDP receive buffer size for socket "
                 + getAddress()
                 + " is set to: "
                 + socketCopy.getReceiveBufferSize());
       }
     } catch (SocketException ex) {
       logger.error(ex);
       setSocketTimeout(0);
     }
   }
   while (!stop) {
     DatagramPacket packet =
         new DatagramPacket(buf, buf.length, udpAddress.getInetAddress(), udpAddress.getPort());
     try {
       socketCopy = socket;
       try {
         if (socketCopy == null) {
           stop = true;
           continue;
         }
         socketCopy.receive(packet);
       } catch (InterruptedIOException iiox) {
         if (iiox.bytesTransferred <= 0) {
           continue;
         }
       }
       if (logger.isDebugEnabled()) {
         logger.debug(
             "Received message from "
                 + packet.getAddress()
                 + "/"
                 + packet.getPort()
                 + " with length "
                 + packet.getLength()
                 + ": "
                 + new OctetString(packet.getData(), 0, packet.getLength()).toHexString());
       }
       ByteBuffer bis;
       // If messages are processed asynchronously (i.e. multi-threaded)
       // then we have to copy the buffer's content here!
       if (isAsyncMsgProcessingSupported()) {
         byte[] bytes = new byte[packet.getLength()];
         System.arraycopy(packet.getData(), 0, bytes, 0, bytes.length);
         bis = ByteBuffer.wrap(bytes);
       } else {
         bis = ByteBuffer.wrap(packet.getData());
       }
       TransportStateReference stateReference =
           new TransportStateReference(
               DefaultUdpTransportMapping.this,
               udpAddress,
               null,
               SecurityLevel.undefined,
               SecurityLevel.undefined,
               false,
               socketCopy);
       fireProcessMessage(
           new UdpAddress(packet.getAddress(), packet.getPort()), bis, stateReference);
     } catch (SocketTimeoutException stex) {
       // ignore
     } catch (PortUnreachableException purex) {
       synchronized (DefaultUdpTransportMapping.this) {
         listener = null;
       }
       logger.error(purex);
       if (logger.isDebugEnabled()) {
         purex.printStackTrace();
       }
       if (SNMP4JSettings.isFowardRuntimeExceptions()) {
         throw new RuntimeException(purex);
       }
       break;
     } catch (SocketException soex) {
       if (!stop) {
         logger.error(
             "Socket for transport mapping " + toString() + " error: " + soex.getMessage(),
             soex);
       }
       if (SNMP4JSettings.isFowardRuntimeExceptions()) {
         stop = true;
         throw new RuntimeException(soex);
       }
     } catch (IOException iox) {
       logger.warn(iox);
       if (logger.isDebugEnabled()) {
         iox.printStackTrace();
       }
       if (SNMP4JSettings.isFowardRuntimeExceptions()) {
         throw new RuntimeException(iox);
       }
     }
   }
   synchronized (DefaultUdpTransportMapping.this) {
     listener = null;
     stop = true;
     DatagramSocket closingSocket = socket;
     if ((closingSocket != null) && (!closingSocket.isClosed())) {
       closingSocket.close();
     }
   }
   if (logger.isDebugEnabled()) {
     logger.debug("Worker task stopped:" + getClass().getName());
   }
 }