Ejemplo n.º 1
0
func (self *apnsPushService) singlePush(req *pushRequest, pool *connpool.Pool, mid uint32, token []byte) {
	conn, err := pool.Get()
	if err != nil {
		req.errChan <- err
		return
	}
	defer conn.Close()
	// 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

	payload := req.payload

	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, req.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()
	err = writen(conn, pdu)
	if err != nil {
		req.errChan <- err
		return
	}

}
Ejemplo n.º 2
0
func (self *apnsPushService) singlePush(payload, token []byte, expiry uint32, mid uint32, pool *connpool.Pool, errChan chan<- error) {
	conn, err := pool.Get()
	if err != nil {
		errChan <- err
		return
	}
	// Total size for each notification:
	//
	// - command: 1
	// - identifier: 4
	// - expiry: 4
	// - device token length: 2
	// - device token: variable (100 max) - apple announced that we might have 100-byte device tokens in the future, in WWDC 2015. Previously 32.
	// - payload length: 2
	// - payload: variable (2048 max)
	//
	// In total, 2161 bytes (max)
	var dataBuffer [2180]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)

	sleepTime := time.Duration(maxWaitTime) * time.Second
	for nrRetries := 0; err != nil && nrRetries < 3; nrRetries++ {
		errChan <- fmt.Errorf("error on connection with %v: %v. Will retry within %v", conn.RemoteAddr(), err, sleepTime)
		errChan = self.errChan
		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 {
			// The pool may return nil for conn.
			if conn != nil {
				conn.Close()
			}
			errChan <- fmt.Errorf("We are unable to get a connection: %v", err)
			return
		}
		deadline := time.Now().Add(sleepTime)
		conn.SetWriteDeadline(deadline)
		err = writen(conn, pdu)
	}
	conn.SetWriteDeadline(time.Time{})
	conn.Close()
}
Ejemplo n.º 3
0
func (self *apnsPushService) singlePush(payload, token []byte, expiry uint32, mid uint32, pool *connpool.Pool, errChan chan<- error) {
	conn, err := pool.Get()
	if err != nil {
		errChan <- err
		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)

	sleepTime := time.Duration(maxWaitTime) * time.Second
	for nrRetries := 0; err != nil && nrRetries < 3; nrRetries++ {
		errChan <- fmt.Errorf("error on connection with %v: %v. Will retry within %v", conn.RemoteAddr(), err, sleepTime)
		errChan = self.errChan
		conn.Close()

		time.Sleep(sleepTime)
		sleepTime = sleepTime * 2
		// Let's try another connection to see if we can recover this error
		conn, err = pool.Get()

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