@Override public void onHeadersRead(final ChannelHandlerContext context, final int streamId, final Http2Headers headers, final int padding, final boolean endOfStream) throws Http2Exception { log.trace("Received headers from APNs gateway on stream {}: {}", streamId, headers); if (endOfStream) { final HttpResponseStatus status = HttpResponseStatus.parseLine(headers.status()); final boolean success = HttpResponseStatus.OK.equals(status); if (!success) { log.warn("Gateway sent an end-of-stream HEADERS frame for an unsuccessful notification."); } final ApnsPushNotification pushNotification = ApnsClientHandler.this.pushNotificationsByStreamId.remove(streamId); ApnsClientHandler.this.authenticationTokensByStreamId.remove(streamId); if (HttpResponseStatus.INTERNAL_SERVER_ERROR.equals(status)) { ApnsClientHandler.this.apnsClient.handleServerError(pushNotification, null); } else { ApnsClientHandler.this.apnsClient.handlePushNotificationResponse( new SimplePushNotificationResponse<>(pushNotification, success, null, null)); } } else { ApnsClientHandler.this.headersByStreamId.put(streamId, headers); } }
@Override public int onDataRead(final ChannelHandlerContext context, final int streamId, final ByteBuf data, final int padding, final boolean endOfStream) throws Http2Exception { log.trace("Received data from APNs gateway on stream {}: {}", streamId, data.toString(StandardCharsets.UTF_8)); final int bytesProcessed = data.readableBytes() + padding; if (endOfStream) { final Http2Headers headers = ApnsClientHandler.this.headersByStreamId.remove(streamId); final String authenticationToken = ApnsClientHandler.this.authenticationTokensByStreamId.remove(streamId); final ApnsPushNotification pushNotification = ApnsClientHandler.this.pushNotificationsByStreamId.remove(streamId); final HttpResponseStatus status = HttpResponseStatus.parseLine(headers.status()); final String responseBody = data.toString(StandardCharsets.UTF_8); if (HttpResponseStatus.INTERNAL_SERVER_ERROR.equals(status)) { ApnsClientHandler.this.apnsClient.handleServerError(pushNotification, responseBody); } else { final ErrorResponse errorResponse = gson.fromJson(responseBody, ErrorResponse.class); if (ApnsClient.EXPIRED_AUTH_TOKEN_REASON.equals(errorResponse.getReason())) { try { ApnsClientHandler.this.apnsClient.getAuthenticationTokenSupplierForTopic(pushNotification.getTopic()).invalidateToken(authenticationToken); } catch (final NoKeyForTopicException e) { // This should only happen if somebody de-registered the topic after a notification was sent log.warn("Authentication token expired, but no key registered for topic {}", pushNotification.getTopic()); } } ApnsClientHandler.this.apnsClient.handlePushNotificationResponse( new SimplePushNotificationResponse<>(pushNotification, HttpResponseStatus.OK.equals(status), errorResponse.getReason(), errorResponse.getTimestamp())); } } else { log.error("Gateway sent a DATA frame that was not the end of a stream."); } return bytesProcessed; }