@SuppressWarnings("unused")
	@Override
	protected boolean handleServiceType(final KNXnetIPHeader h, final byte[] data, final int offset,
		final InetAddress src, final int port) throws KNXFormatException, IOException
	{
		final int svc = h.getServiceType();
		if (svc == KNXnetIPHeader.CONNECT_REQ)
			logger.warn("received connect request - ignored");
		else if (svc == KNXnetIPHeader.CONNECT_RES) {
			final ConnectResponse res = new ConnectResponse(data, offset);
			// we do an additional check for UDP to be on the safe side
			// endpoint is only != null on no error
			final HPAI ep = res.getDataEndpoint();
			if (res.getStatus() == ErrorCodes.NO_ERROR && ep.getHostProtocol() == HPAI.IPV4_UDP) {
				channelId = res.getChannelID();
				final InetAddress ip = ep.getAddress();
				// in NAT aware mode, if the data EP is incomplete or left
				// empty, we fall back to the IP address and port of the sender
				if (useNat && (ip == null || ip.isAnyLocalAddress() || ep.getPort() == 0)) {
					dataEndpt = new InetSocketAddress(src, port);
				}
				else {
					dataEndpt = new InetSocketAddress(ip, ep.getPort());
				}

				if (res.getCRD() instanceof TunnelCRD)
					tunnelingAddress = ((TunnelCRD) res.getCRD()).getAssignedAddress();

				checkVersion(h);
				setStateNotify(OK);
				return true;
			}
			if (ep != null && ep.getHostProtocol() != HPAI.IPV4_UDP)
				status = "server does not agree with UDP/IP";
			else
				status = res.getStatusString();

			logger.error(status);
			setStateNotify(ACK_ERROR);
		}
		else if (svc == KNXnetIPHeader.CONNECTIONSTATE_REQ)
			logger.warn("received connection state request - ignored");
		else if (svc == KNXnetIPHeader.CONNECTIONSTATE_RES) {
			if (checkVersion(h))
				heartbeat.setResponse(new ConnectionstateResponse(data, offset));
		}
		else if (svc == KNXnetIPHeader.DISCONNECT_REQ) {
			if (ctrlEndpt.getAddress().equals(src) && ctrlEndpt.getPort() == port)
				disconnectRequested(new DisconnectRequest(data, offset));
		}
		else if (svc == KNXnetIPHeader.DISCONNECT_RES) {
			final DisconnectResponse res = new DisconnectResponse(data, offset);
			if (res.getStatus() != ErrorCodes.NO_ERROR)
				logger.warn("received disconnect response status 0x"
						+ Integer.toHexString(res.getStatus()) + " ("
						+ ErrorCodes.getErrorMessage(res.getStatus()) + ")");
			// finalize closing
			closing = 2;
			setStateNotify(CLOSED);
		}
		else if (svc == serviceAck) {
			final ServiceAck res = new ServiceAck(svc, data, offset);
			if (!checkChannelId(res.getChannelID(), "acknowledgment"))
				return true;
			if (res.getSequenceNumber() != getSeqSend())
				logger.warn("received service acknowledgment with wrong send sequence "
						+ res.getSequenceNumber() + ", expected " + getSeqSend() + " - ignored");
			else {
				if (!checkVersion(h))
					return true;
				incSeqSend();
				// update state and notify our lock
				setStateNotify(res.getStatus() == ErrorCodes.NO_ERROR ? CEMI_CON_PENDING
						: ACK_ERROR);
				if (logger.isTraceEnabled())
					logger.trace("received service ack {} from {} (channel {})",
							res.getSequenceNumber(), ctrlEndpt, channelId);
				if (internalState == ACK_ERROR)
					logger.warn("received service acknowledgment status " + res.getStatusString());
			}
		}
		else
			return false;
		return true;
	}
@ SuppressWarnings ( "unused" ) @ Override protected boolean handleServiceType ( final KNXnetIPHeader h , final byte [ ] data , final int offset , final InetAddress src , final int port ) throws KNXFormatException , IOException { final int svc = h . getServiceType ( ) ; if ( svc == KNXnetIPHeader . CONNECT_REQ ) logger . warn ( "received connect request - ignored" ) ; else if ( svc == KNXnetIPHeader . CONNECT_RES ) { final ConnectResponse res = new ConnectResponse ( data , offset ) ; final HPAI ep = res . getDataEndpoint ( ) ; if ( res . getStatus ( ) == ErrorCodes . NO_ERROR && ep . getHostProtocol ( ) == HPAI . IPV4_UDP ) { channelId = res . getChannelID ( ) ; final InetAddress ip = ep . getAddress ( ) ; if ( useNat && ( ip == null || ip . isAnyLocalAddress ( ) || ep . getPort ( ) == 0 ) ) { dataEndpt = new InetSocketAddress ( src , port ) ; } else { dataEndpt = new InetSocketAddress ( ip , ep . getPort ( ) ) ; } if ( res . getCRD ( ) instanceof TunnelCRD ) tunnelingAddress = ( ( TunnelCRD ) res . getCRD ( ) ) . getAssignedAddress ( ) ; checkVersion ( h ) ; setStateNotify ( OK ) ; return true ; } if ( ep != null && ep . getHostProtocol ( ) != HPAI . IPV4_UDP ) status = "server does not agree with UDP/IP" ; else status = res . getStatusString ( ) ; logger . error ( status ) ; setStateNotify ( ACK_ERROR ) ; } else if ( svc == KNXnetIPHeader . CONNECTIONSTATE_REQ ) logger . warn ( "received connection state request - ignored" ) ; else if ( svc == KNXnetIPHeader . CONNECTIONSTATE_RES ) { if ( checkVersion ( h ) ) heartbeat . setResponse ( new ConnectionstateResponse ( data , offset ) ) ; } else if ( svc == KNXnetIPHeader . DISCONNECT_REQ ) { if ( ctrlEndpt . getAddress ( ) . equals ( src ) && ctrlEndpt . getPort ( ) == port ) disconnectRequested ( new DisconnectRequest ( data , offset ) ) ; } else if ( svc == KNXnetIPHeader . DISCONNECT_RES ) { final DisconnectResponse res = new DisconnectResponse ( data , offset ) ; if ( res . getStatus ( ) != ErrorCodes . NO_ERROR ) logger . warn ( "received disconnect response status 0x" + Integer . toHexString ( res . getStatus ( ) ) + " (" + ErrorCodes . getErrorMessage ( res . getStatus ( ) ) + ")" ) ; closing = 2 ; setStateNotify ( CLOSED ) ; } else if ( svc == serviceAck ) { final ServiceAck res = new ServiceAck ( svc , data , offset ) ; if ( ! checkChannelId ( res . getChannelID ( ) , "acknowledgment" ) ) return true ; if ( res . getSequenceNumber ( ) != getSeqSend ( ) ) logger . warn ( "received service acknowledgment with wrong send sequence " + res . getSequenceNumber ( ) + ", expected " + getSeqSend ( ) + " - ignored" ) ; else { if ( ! checkVersion ( h ) ) return true ; incSeqSend ( ) ; setStateNotify ( res . getStatus ( ) == ErrorCodes . NO_ERROR ? CEMI_CON_PENDING : ACK_ERROR ) ; if ( logger . isTraceEnabled ( ) ) logger . trace ( "received service ack {} from {} (channel {})" , res . getSequenceNumber ( ) , ctrlEndpt , channelId ) ; if ( internalState == ACK_ERROR ) logger . warn ( "received service acknowledgment status " + res . getStatusString ( ) ) ; } } else return false ; return true ; }
@see tuwien.auto.calimero.knxnetip.ConnectionBase#handleServiceType
(tuwien.auto.calimero.knxnetip.servicetype.KNXnetIPHeader, byte[], int, java.net.InetAddress, int)
@throws KNXFormatException if the received service type consists of an invalid structure
@throws IOException on socket I/O error