--- ../asterisk/channels/chan_sip.c	2006-03-27 12:28:31.822344160 -0600
+++ channels/chan_sip.c	2006-03-27 12:25:55.517106168 -0600
@@ -537,6 +537,15 @@
 	struct sip_auth *next;		/*!< Next auth structure in list */
 };
 
+/*! \brief hintmgrparam: A structure to hold on to pointers for cb_hintmanager */
+struct hintmgrparam {
+	int state;			/*!< The original state causing the cb */
+	char *context;			/*!< Context the hint is for */
+	char *exten;			/*!< Extension the hint is for */
+	struct sip_pvt *p;		/*!< SIP Session Structure Ptr */
+};
+
+
 /*--- Various flags for the flags field in the pvt structure 
  Peer only flags should be set in PAGE2 below
 */
@@ -971,6 +980,7 @@
 static int determine_firstline_parts(struct sip_request *req);
 static void sip_dump_history(struct sip_pvt *dialog);	/* Dump history to LOG_DEBUG at end of dialog, before destroying data */
 static const struct cfsubscription_types *find_subscription_type(enum subscriptiontype subtype);
+static int cb_extensionstate(char *context, char* exten, int state, void *data);
 static int transmit_state_notify(struct sip_pvt *p, int state, int full);
 static char *gettag(struct sip_request *req, char *header, char *tagbuf, int tagbufsize);
 static int find_sip_method(char *msg);
@@ -6497,29 +6507,70 @@
 	}
 }
 
+/*! \brief  cb_hintmanager: Callback to check on the status of an AST_EXTENSION_DEACTIVATED/REMOVED call already received ---*/
+/*    When you do a 'reload' in Asterisk the ast_merge_contexts_and_delete() function call that gets
+      called during the reload will rebuild hints sending AST_EXTENSION_DEACTIVATED state msgs. Now, instead of 
+      acting immediately on those msgs, we schedule this callback for 5 secs later and if the hint is 
+      still not there, then we tear down the subscription, otherwise, we re-establish our connection with 
+      the core and re-sync and re-transmit current state. */
+static int cb_hintmanager(void *data)
+{
+	struct hintmgrparam *hmgrp = data;
+	struct sip_pvt *p = NULL;
+	int firststate = hmgrp->state;
+
+	/* Verify first that the SIP session is still around after having waited 5 secs */
+	if (hmgrp->p) {
+		p = hmgrp->p;
+		p->stateid = ast_extension_state_add(p->context, p->exten, cb_extensionstate, p);
+		ast_log(LOG_DEBUG, "ast_extension_state on %s@%s is %d\n", p->exten, p->context, ast_extension_state(NULL, p->context, p->exten));
+		if ((firststate = ast_extension_state(NULL, p->context, p->exten)) < 0) {
+			ast_log(LOG_DEBUG, "Still cannot retrieve state on %s@%s. Time to throw in the towel.\n", p->exten, p->context);
+			if (p->autokillid > -1)
+				sip_cancel_destroy(p);		/* Remove subscription expiry for renewals */
+			sip_scheddestroy(p, 10000);		/* Delete subscription in 10 more secs since we've already waited 5 */
+			ast_verbose(VERBOSE_PREFIX_2 "Extension state: Watcher for hint %s %s. Notify User %s\n", hmgrp->exten, hmgrp->state == AST_EXTENSION_DEACTIVATED ? "deactivated" : "removed", p->username);
+			p->stateid = -1;
+			p->subscribed = NONE;
+			append_history(p, "Subscribestatus", "%s", hmgrp->state == AST_EXTENSION_REMOVED ? "HintRemoved" : "Deactivated");
+			transmit_state_notify(p, hmgrp->state, 1);
+		} else {
+			if (option_debug > 1)
+				ast_verbose(VERBOSE_PREFIX_1 "Extension State Resync %s new state %s for Notify User %s\n", hmgrp->exten, ast_extension_state2str(firststate), p->username);
+				transmit_state_notify(p, firststate, 1);	/* Send current notification */
+		}	
+	} else
+		ast_log(LOG_DEBUG, "The SIP Session has gone away while we were waiting to be called back. Cleaning up and done.\n");
+
+	return 0;
+}
+
 /*! \brief Callback for the devicestate notification (SUBSCRIBE) support subsystem
 \note	If you add an "hint" priority to the extension in the dial plan,
 	you will get notifications on device state changes */
 static int cb_extensionstate(char *context, char* exten, int state, void *data)
 {
 	struct sip_pvt *p = data;
+	struct hintmgrparam *hmgrp = NULL;
 
 	switch(state) {
 	case AST_EXTENSION_DEACTIVATED:	/* Retry after a while */
 	case AST_EXTENSION_REMOVED:	/* Extension is gone */
-		if (p->autokillid > -1)
-			sip_cancel_destroy(p);	/* Remove subscription expiry for renewals */
-		sip_scheddestroy(p, 15000);	/* Delete subscription in 15 secs */
-		ast_verbose(VERBOSE_PREFIX_2 "Extension state: Watcher for hint %s %s. Notify User %s\n", exten, state == AST_EXTENSION_DEACTIVATED ? "deactivated" : "removed", p->username);
-		p->stateid = -1;
-		p->subscribed = NONE;
-		append_history(p, "Subscribestatus", "%s", state == AST_EXTENSION_REMOVED ? "HintRemoved" : "Deactivated");
+		hmgrp = ast_calloc(1, sizeof(*hmgrp));
+		hmgrp->state = state;
+		hmgrp->context = context;
+		hmgrp->exten = exten;
+		hmgrp->p = p;
+		ast_sched_add_variable_and_cleanup(sched, 5000, cb_hintmanager, hmgrp, 0, hmgrp);
 		break;
 	default:	/* Tell user */
 		p->laststate = state;
 		break;
 	}
-	transmit_state_notify(p, state, 1);
+
+	if (state != AST_EXTENSION_DEACTIVATED && state != AST_EXTENSION_REMOVED)
+		transmit_state_notify(p, state, 1);
+
 
 	if (option_debug > 1)
 		ast_verbose(VERBOSE_PREFIX_1 "Extension Changed %s new state %s for Notify User %s\n", exten, ast_extension_state2str(state), p->username);
