Helper function for the redisAsyncCommand* family of functions. Writes a * formatted command to the output buffer and registers the provided callback * function with the context. */
| 735 | * formatted command to the output buffer and registers the provided callback |
| 736 | * function with the context. */ |
| 737 | static int __redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *cmd, size_t len) { |
| 738 | redisContext *c = &(ac->c); |
| 739 | redisCallback cb; |
| 740 | struct dict *cbdict; |
| 741 | dictEntry *de; |
| 742 | redisCallback *existcb; |
| 743 | int pvariant, hasnext; |
| 744 | const char *cstr, *astr; |
| 745 | size_t clen, alen; |
| 746 | const char *p; |
| 747 | hisds sname; |
| 748 | int ret; |
| 749 | |
| 750 | /* Don't accept new commands when the connection is about to be closed. */ |
| 751 | if (c->flags & (REDIS_DISCONNECTING | REDIS_FREEING)) return REDIS_ERR; |
| 752 | |
| 753 | /* Setup callback */ |
| 754 | cb.fn = fn; |
| 755 | cb.privdata = privdata; |
| 756 | cb.pending_subs = 1; |
| 757 | |
| 758 | /* Find out which command will be appended. */ |
| 759 | p = nextArgument(cmd,&cstr,&clen); |
| 760 | assert(p != NULL); |
| 761 | hasnext = (p[0] == '$'); |
| 762 | pvariant = (tolower(cstr[0]) == 'p') ? 1 : 0; |
| 763 | cstr += pvariant; |
| 764 | clen -= pvariant; |
| 765 | |
| 766 | if (hasnext && strncasecmp(cstr,"subscribe\r\n",11) == 0) { |
| 767 | c->flags |= REDIS_SUBSCRIBED; |
| 768 | |
| 769 | /* Add every channel/pattern to the list of subscription callbacks. */ |
| 770 | while ((p = nextArgument(p,&astr,&alen)) != NULL) { |
| 771 | sname = hi_sdsnewlen(astr,alen); |
| 772 | if (sname == NULL) |
| 773 | goto oom; |
| 774 | |
| 775 | if (pvariant) |
| 776 | cbdict = ac->sub.patterns; |
| 777 | else |
| 778 | cbdict = ac->sub.channels; |
| 779 | |
| 780 | de = dictFind(cbdict,sname); |
| 781 | |
| 782 | if (de != NULL) { |
| 783 | existcb = dictGetEntryVal(de); |
| 784 | cb.pending_subs = existcb->pending_subs + 1; |
| 785 | } |
| 786 | |
| 787 | ret = dictReplace(cbdict,sname,&cb); |
| 788 | |
| 789 | if (ret == 0) hi_sdsfree(sname); |
| 790 | } |
| 791 | } else if (strncasecmp(cstr,"unsubscribe\r\n",13) == 0) { |
| 792 | /* It is only useful to call (P)UNSUBSCRIBE when the context is |
| 793 | * subscribed to one or more channels or patterns. */ |
| 794 | if (!(c->flags & REDIS_SUBSCRIBED)) return REDIS_ERR; |
no test coverage detected