Beispiel #1
0
func (self *apnsPushService) singlePush(payload, token []byte, expiry uint32, mid uint32, pool *connpool.Pool) {
	conn, err := pool.Get()
	if err != nil {
		for i := 0; i < 3; i++ {
			conn, err = pool.Get()
			if err != nil {
				self.logChan <- NewInfof("singlePush pool get err:%v token:%v", err, hex.EncodeToString(token))
				continue
			}
			break
		}
		if err != nil {
			clearRequest(self.pushRet, 3, mid, 0)
			self.logChan <- NewInfof("Alas helpless... err:%v token:%v", err, hex.EncodeToString(token))
			return
		}
	}

	// Total size for each notification:
	//
	// - command: 1
	// - identifier: 4
	// - expiry: 4
	// - device token length: 2
	// - device token: 32 (vary)
	// - payload length: 2
	// - payload: vary (256 max)
	//
	// In total, 301 bytes (max)
	var dataBuffer [2048]byte

	buffer := bytes.NewBuffer(dataBuffer[:0])
	// command
	binary.Write(buffer, binary.BigEndian, uint8(1))
	// transaction id
	binary.Write(buffer, binary.BigEndian, mid)

	// Expiry
	binary.Write(buffer, binary.BigEndian, expiry)

	// device token
	binary.Write(buffer, binary.BigEndian, uint16(len(token)))
	buffer.Write(token)

	// payload
	binary.Write(buffer, binary.BigEndian, uint16(len(payload)))
	buffer.Write(payload)

	pdu := buffer.Bytes()

	deadline := time.Now().Add(time.Duration(maxWaitTime) * time.Second)
	conn.SetWriteDeadline(deadline)

	err = writen(conn, pdu)

	//self.logChan <- NewInfof("writen token::%v err:%v LocalAddr:%v cid:%v mid:%v pdu:%v", hex.EncodeToString(token), err, conn.LocalAddr(), conn.Id(), mid, len(pdu))
	//fmt.Println("writen token:", hex.EncodeToString(token), " err:", err, " LocalAddr:", conn.LocalAddr(), " cid", conn.Id(), " mid:", mid)

	sleepTime := time.Duration(maxWaitTime) * time.Second
	for nrRetries := 0; err != nil && nrRetries < 3; nrRetries++ {
		self.logChan <- NewInfof("error on connection with %v. Will retry within %v   %v", err, sleepTime, hex.EncodeToString(token))

		conn.Close()
		time.Sleep(sleepTime)
		// randomly wait more time
		sleepTime += time.Duration(rand.Int63n(int64(sleepTime)))
		// Let's try another connection to see if we can recover this error
		conn, err = pool.Get()

		if err != nil {
			self.logChan <- NewInfof("We are unable to get a connection: %v", err)
			if conn != nil {
				conn.Close()
			}
			return
		}
		deadline := time.Now().Add(sleepTime)
		conn.SetWriteDeadline(deadline)
		err = writen(conn, pdu)
	}

	if err != nil {
		clearRequest(self.pushRet, 3, mid, 0)
		self.logChan <- NewInfof("token send fail: %v  err:%v LocalAddr:%v", hex.EncodeToString(token), err, conn.LocalAddr())
	} else {
		clearRequest(self.pushRet, 1, mid, conn.Id())
	}

	conn.SetWriteDeadline(time.Time{})
	conn.Close()
}