def send_notification(self, token_hex, payload, identifier=0, expiry=0):
        if self.enhanced:
            self._last_activity_time = time.time()
            message = self._get_enhanced_notification(token_hex, payload,
                                                           identifier, expiry)
            _logger.debug("message: %s" % b2a_hex(message))
            timeout_sec = 2
            timeout_tot = 0
            i = 0
            _succ = False
            while timeout_tot < 30:
                try:
                    with self._send_lock:
                        timeout_tot += timeout_sec
                        i += 1
                        #self._make_sure_error_response_handler_worker_alive()
                        self.write(message)
                        self._sent_notifications.append(dict({'id': identifier, 'message': message}))
                        _logger.debug("send notification to APNS.")
                        
                        rlist, _, _ = select.select([self._connection()], [], [], WAIT_READ_TIMEOUT_SEC)
                        _logger.debug("got response from APNS: %d" % len(rlist))
                        if len(rlist) > 0: # there's some data from APNs
                            self._socket.settimeout(0.5)
                            buff = self.read(ERROR_RESPONSE_LENGTH)
                            if len(buff) == ERROR_RESPONSE_LENGTH:
                                command, status, identifier = unpack(ERROR_RESPONSE_FORMAT, buff)
                                if 8 == command: # there is error response from APNS
                                    #if self._response_listener:
                                    #    self._response_listener(Util.convert_error_response_to_dict(error_response))
                                    _logger.info("got error-response from APNS: %d" % status)
                                    self._disconnect()
                                    #self._resend_notifications_by_id(identifier)
                            if len(buff) == 0:
                                _logger.warning("read socket got 0 bytes data") #DEBUG
                                self._disconnect()
                        
                        _succ = True
                    break
                except socket_error as e:
                    timeout_sec *= 2
                    _logger.exception("sending notification with id:" + str(identifier) + 
                                 " to APNS failed: " + str(type(e)) + ": " + str(e) + 
                                 " in " + str(i+1) + "th attempt, will wait " + str(timeout_sec) + " secs for next action")
                    time.sleep(timeout_sec) # wait potential error-response to be read
            
            return _succ
        else:
            message = self._get_notification(token_hex, payload)
            _logger.debug("message: %s" % b2a_hex(message))
            self.write(message)
            return True
    
    # def _make_sure_error_response_handler_worker_alive(self):
#         if (not self._error_response_handler_worker 
#             or not self._error_response_handler_worker.is_alive()):
#             self._init_error_response_handler_worker()
#             TIMEOUT_SEC = 10
#             for _ in xrange(TIMEOUT_SEC):
#                 if self._error_response_handler_worker.is_alive():
#                     _logger.debug("error response handler worker is running")
#                     return
#                 time.sleep(1)
#             _logger.warning("error response handler worker is not started after %s secs" % TIMEOUT_SEC)
in enhanced mode, send_notification may return error response from APNs if any
dataset/ETHPy150Open SafeSlingerProject/SafeSlinger-AppEngine/safeslinger-messenger/python/apns_enhanced.py/GatewayConnection.send_notification