From af771f1355651da66da4421f6b6369303f350657 Mon Sep 17 00:00:00 2001 From: Kendrick Chan Date: Wed, 14 Nov 2018 01:39:34 +0800 Subject: [PATCH] Get rid of third party library for APNS sending #170 --- utils/apns_sender/apns_sender.py | 73 +++++++++++++++++++++++++------- 1 file changed, 57 insertions(+), 16 deletions(-) diff --git a/utils/apns_sender/apns_sender.py b/utils/apns_sender/apns_sender.py index 7fed3105..ce3a4823 100644 --- a/utils/apns_sender/apns_sender.py +++ b/utils/apns_sender/apns_sender.py @@ -1,6 +1,5 @@ -from threading import Thread from daemonize import Daemonize -from apns import APNs, Payload +#from apns import APNs, Payload import redis import time import signal @@ -9,6 +8,10 @@ import os import logging import socket +import ssl +import struct +import binascii + def sigint_handler(signal, frame): @@ -18,13 +21,14 @@ def sigint_handler(signal, frame): def redisLoop(apns, logger): r = redis.StrictRedis(host='localhost', port=6379, db=0) while 1: + #logger.info("Checking queue for messages to send...") time.sleep(0) data = r.brpop("apns_push", 10) if data: info = data[1].split('|') logger.info("Token: " + info[0] + " message: " + info[1]) try: - send_notif(apns, info[0], info[1]) + apns.sendNotification(info[0], info[1]) except TypeError: logger.info("Invalid token: " + info[0]) @@ -32,14 +36,6 @@ def redisLoop(apns, logger): def sigint_handler(signal, frame): sys.exit(0) -def send_notif(apns, token_hex, message): - #token_hex = '602E96BF9BC15D7913871D4D90FEBD7E265500C9D22DCEC5A4AFA3FC36EBE4DC' - payload = Payload(alert=message, sound="default", badge=1) - try: - apns.gateway_server.send_notification(token_hex, payload) - except socket.error: - apns = setup_apns() - def get_logger(): logger = logging.getLogger("apns_logger") logger.setLevel(logging.INFO) @@ -52,17 +48,62 @@ def get_logger(): logger.addHandler(fh) return logger -def setup_apns(): - cert_file = "/root/ios_push_test/ios_prod.pem" - apns = APNs(use_sandbox=True, cert_file=cert_file) - return apns +class APNSClient(): + def __init__(self, host, port, cert_file, logger): + self.host = host + self.port = port + self.cert_file = cert_file + self.logger = logger + self.is_connected = False + + def setupConnection(self): + # socket + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + wsock = ssl.wrap_socket(sock, ssl_version=ssl.PROTOCOL_TLSv1, certfile=self.cert_file) + wsock.connect((self.host, self.port)) + + self.is_connected = True + self.conn = wsock + + return wsock + + def connect(self): + if not self.is_connected: + self.setupConnection() + + def sendNotification(self, token, message): + # connect + self.connect() + + # apns packet + payload = '{"aps": {"alert" : "%s", "sound": "bingbong.aiff"}}' % message + bin_token = binascii.unhexlify(token) + fmt = "!cH32sH%ds" % len(payload) + cmd = '\x00' + packet = struct.pack(fmt, cmd, len(bin_token), bin_token, len(payload), payload) + + # send packet + self.conn.send(packet) + + # TODO: figure out how to make this connection persistent + self.conn.close() + self.is_connected = False + def main(): logger = get_logger() logger.info("Starting apns_sender") + #apns = APNs(use_sandbox=False, cert_file=cert_file) - apns = setup_apns() + #apns = setup_apns() + + # TODO: load from config file + cert_file = "/root/ios_push_test/ios_prod.pem" + host = 'gateway.push.apple.com' + port = 2195 + apns = APNSClient(host, port, cert_file, logger) + logger.info("Starting redis loop") redisLoop(apns, logger)