func (f *pushDatabaseOpts) ModifyPushServiceProvider(psp *push.PushServiceProvider) error { if len(psp.Name()) == 0 { return nil } f.dblock.Lock() defer f.dblock.Unlock() return addErrorSource("ModifyPushServiceProvider", f.db.SetPushServiceProvider(psp)) }
func (f *pushDatabaseOpts) AddPushServiceProviderToService(service string, push_service_provider *push.PushServiceProvider) error { if push_service_provider == nil { return nil } name := push_service_provider.Name() if len(name) == 0 { return errors.New("InvalidPushServiceProvider") } f.dblock.Lock() defer f.dblock.Unlock() e := f.db.SetPushServiceProvider(push_service_provider) if e != nil { return fmt.Errorf("Error associating psp with name: %v", e) } return f.db.AddPushServiceProviderToService(service, push_service_provider.Name()) }
func (f *pushDatabaseOpts) RemovePushServiceProviderFromService(service string, push_service_provider *push.PushServiceProvider) error { name := push_service_provider.Name() if name == "" { return errors.New("InvalidPushServiceProvider") } db := f.db f.dblock.Lock() defer f.dblock.Unlock() err := db.RemovePushServiceProviderFromService(service, name) if err != nil { return fmt.Errorf("Error removing the psp: %v", err) } err = db.RemovePushServiceProvider(name) if err != nil { return fmt.Errorf("Error removing the psp label: %v", err) } return nil }
func (self *RestAPI) changeSubscription(kv map[string]string, logger log.Logger, remoteAddr string, issub bool) ApiResponseDetails { dp, err := self.psm.BuildDeliveryPointFromMap(kv) if err != nil { logger.Errorf("Cannot build delivery point: %v", err) return ApiResponseDetails{From: &remoteAddr, Code: UNIQUSH_ERROR_BUILD_DELIVERY_POINT, ErrorMsg: strPtrOfErr(err)} } service, err := getServiceFromMap(kv, true) if err != nil { logger.Errorf("From=%v Cannot get service name: %v; %v", remoteAddr, service, err) return ApiResponseDetails{From: &remoteAddr, Service: &service, Code: UNIQUSH_ERROR_CANNOT_GET_SERVICE, ErrorMsg: strPtrOfErr(err)} } subs, err := getSubscribersFromMap(kv, true) if err != nil { logger.Errorf("From=%v Service=%v Cannot get subscriber: %v", remoteAddr, service, err) return ApiResponseDetails{From: &remoteAddr, Service: &service, Code: UNIQUSH_ERROR_CANNOT_GET_SUBSCRIBER, ErrorMsg: strPtrOfErr(err)} } var psp *push.PushServiceProvider if issub { psp, err = self.backend.Subscribe(service, subs[0], dp) } else { err = self.backend.Unsubscribe(service, subs[0], dp) } if err != nil { logger.Errorf("From=%v Failed: %v", remoteAddr, err) return ApiResponseDetails{From: &remoteAddr, Code: UNIQUSH_ERROR_GENERIC, ErrorMsg: strPtrOfErr(err)} } dpName := dp.Name() if psp == nil { logger.Infof("From=%v Service=%v Subscriber=%v DeliveryPoint=%v Success!", remoteAddr, service, subs[0], dpName) return ApiResponseDetails{From: &remoteAddr, Service: &service, Subscriber: &subs[0], DeliveryPoint: &dpName, Code: UNIQUSH_SUCCESS} } else { pspName := psp.Name() logger.Infof("From=%v Service=%v Subscriber=%v PushServiceProvider=%v DeliveryPoint=%v Success!", remoteAddr, service, subs[0], pspName, dpName) return ApiResponseDetails{From: &remoteAddr, Service: &service, Subscriber: &subs[0], DeliveryPoint: &dpName, PushServiceProvider: &pspName, Code: UNIQUSH_SUCCESS} } }
// Push will read all of the delivery points to send to from dpQueue and send responses on resQueue before closing the channel. If the notification data is invalid, // it will send only one response. func (self *pushService) Push(psp *push.PushServiceProvider, dpQueue <-chan *push.DeliveryPoint, resQueue chan<- *push.PushResult, notif *push.Notification) { defer close(resQueue) // Profiling // self.updateCheckPoint("") var err push.PushError req := new(common.PushRequest) req.PSP = psp req.Payload, err = toAPNSPayload(notif) if err == nil && len(req.Payload) > self.requestProcessor.GetMaxPayloadSize() { err = push.NewBadNotificationWithDetails(fmt.Sprintf("payload is too large: %d > %d", len(req.Payload), self.requestProcessor.GetMaxPayloadSize())) } if err != nil { res := new(push.PushResult) res.Provider = psp res.Content = notif res.Err = push.NewErrorf("Failed to create push: %v", err) resQueue <- res for _ = range dpQueue { } return } unixNow := uint32(time.Now().Unix()) expiry := unixNow + 60*60 if ttlstr, ok := notif.Data["ttl"]; ok { ttl, err := strconv.ParseUint(ttlstr, 10, 32) if err == nil { expiry = unixNow + uint32(ttl) } } req.Expiry = expiry req.Devtokens = make([][]byte, 0, 10) dpList := make([]*push.DeliveryPoint, 0, 10) for dp := range dpQueue { res := new(push.PushResult) res.Destination = dp res.Provider = psp res.Content = notif devtoken, ok := dp.FixedData["devtoken"] if !ok { res.Err = push.NewBadDeliveryPointWithDetails(dp, "NoDevtoken") resQueue <- res continue } btoken, err := hex.DecodeString(devtoken) if err != nil { res.Err = push.NewBadDeliveryPointWithDetails(dp, err.Error()) resQueue <- res continue } req.Devtokens = append(req.Devtokens, btoken) dpList = append(dpList, dp) } n := len(req.Devtokens) lastId := self.getMessageIds(n) req.MaxMsgId = lastId req.DPList = dpList // We send this request object to be processed by pushMux goroutine, to send responses/errors back. errChan := make(chan push.PushError) resChan := make(chan *common.APNSResult, n) req.ErrChan = errChan req.ResChan = resChan self.requestProcessor.AddRequest(req) // errChan closed means the message(s) is/are sent successfully to the APNs. // However, we may have not yet receieved responses from APNS - those are sent on resChan for err = range errChan { res := new(push.PushResult) res.Provider = psp res.Content = notif if _, ok := err.(*push.ErrorReport); ok { res.Err = push.NewErrorf("Failed to send payload to APNS: %v", err) } else { res.Err = err } resQueue <- res } // Profiling // self.updateCheckPoint("sending the message takes") if err != nil { return } for i, dp := range dpList { if dp != nil { r := new(push.PushResult) r.Provider = psp r.Content = notif r.Destination = dp mid := req.GetId(i) r.MsgId = fmt.Sprintf("apns:%v-%v", psp.Name(), mid) r.Err = nil resQueue <- r } } // Wait for the unserialized responses from APNS asynchronously - these will not affect what we send our clients for this request, but will affect subsequent requests. go self.waitResults(psp, dpList, lastId, resChan) }
func (cdb *pushRawDatabaseCache) SetPushServiceProvider(psp *push.PushServiceProvider) error { cdb.pspCache.Set(psp.Name(), psp) return nil }
func (r *PushRedisDB) SetPushServiceProvider(psp *push.PushServiceProvider) error { if err := r.client.Set(PUSH_SERVICE_PROVIDER_PREFIX+psp.Name(), pushServiceProviderToValue(psp), 0).Err(); err != nil { return fmt.Errorf("SetPushServiceProvider %q failed: %v", psp.Name(), err) } return nil }
func pushServiceProviderToValue(psp *push.PushServiceProvider) []byte { return psp.Marshal() }