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 } }
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() }
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() }