mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +00:00 
			
		
		
		
	Correctly handle call flow with outgoing queue, avoiding retries while call acti
ve (bug #1018) git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@2505 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
		| @@ -65,7 +65,7 @@ int fully_booted = 0; | ||||
|  | ||||
| static int ast_socket = -1;		/* UNIX Socket for allowing remote control */ | ||||
| static int ast_consock = -1;		/* UNIX Socket for controlling another asterisk */ | ||||
| static int mainpid; | ||||
| int ast_mainpid; | ||||
| struct console { | ||||
| 	int fd;					/* File descriptor */ | ||||
| 	int p[2];				/* Pipe */ | ||||
| @@ -196,7 +196,7 @@ static void *netconsole(void *vconsole) | ||||
| 	 | ||||
| 	if (gethostname(hostname, sizeof(hostname))) | ||||
| 		strncpy(hostname, "<Unknown>", sizeof(hostname)-1); | ||||
| 	snprintf(tmp, sizeof(tmp), "%s/%d/%s\n", hostname, mainpid, ASTERISK_VERSION); | ||||
| 	snprintf(tmp, sizeof(tmp), "%s/%d/%s\n", hostname, ast_mainpid, ASTERISK_VERSION); | ||||
| 	fdprint(con->fd, tmp); | ||||
| 	for(;;) { | ||||
| 		FD_ZERO(&rfds);	 | ||||
| @@ -1271,7 +1271,7 @@ int main(int argc, char *argv[]) | ||||
| 	} | ||||
| 	if (gethostname(hostname, sizeof(hostname))) | ||||
| 		strncpy(hostname, "<Unknown>", sizeof(hostname)-1); | ||||
| 	mainpid = getpid(); | ||||
| 	ast_mainpid = getpid(); | ||||
| 	ast_ulaw_init(); | ||||
| 	ast_alaw_init(); | ||||
| 	callerid_init(); | ||||
| @@ -1500,7 +1500,7 @@ int main(int argc, char *argv[]) | ||||
| 		/* Register our quit function */ | ||||
| 		char title[256]; | ||||
| 		set_icon("Asterisk"); | ||||
| 		snprintf(title, sizeof(title), "Asterisk Console on '%s' (pid %d)", hostname, mainpid); | ||||
| 		snprintf(title, sizeof(title), "Asterisk Console on '%s' (pid %d)", hostname, ast_mainpid); | ||||
| 		set_title(title); | ||||
| 	    ast_cli_register(&quit); | ||||
| 	    ast_cli_register(&astexit); | ||||
|   | ||||
| @@ -29,6 +29,7 @@ extern int fully_booted; | ||||
| extern char defaultlanguage[]; | ||||
| extern time_t ast_startuptime; | ||||
| extern time_t ast_lastreloadtime; | ||||
| extern int ast_mainpid; | ||||
|  | ||||
| #define VERBOSE_PREFIX_1 " " | ||||
| #define VERBOSE_PREFIX_2 "  == " | ||||
|   | ||||
| @@ -50,6 +50,8 @@ struct outgoing { | ||||
| 	int retrytime; | ||||
| 	/* How long to wait for an answer */ | ||||
| 	int waittime; | ||||
| 	/* PID which is currently calling */ | ||||
| 	int callingpid; | ||||
| 	 | ||||
| 	/* What to connect to outgoing */ | ||||
| 	char tech[256]; | ||||
| @@ -157,6 +159,14 @@ static int apply_outgoing(struct outgoing *o, char *fn, FILE *f) | ||||
| 						} | ||||
| 					} else if (!strcasecmp(buf, "retry")) { | ||||
| 						o->retries++; | ||||
| 					} else if (!strcasecmp(buf, "startretry")) { | ||||
| 						if (sscanf(c, "%d", &o->callingpid) != 1) { | ||||
| 							ast_log(LOG_WARNING, "Unable to retrieve calling PID!\n"); | ||||
| 							o->callingpid = 0; | ||||
| 						} | ||||
| 					} else if (!strcasecmp(buf, "endretry") || !strcasecmp(buf, "abortretry")) { | ||||
| 						o->callingpid = 0; | ||||
| 						o->retries++; | ||||
| 					} else if (!strcasecmp(buf, "setvar")) { /* JDG variable support */ | ||||
| 						strncat(o->variable, c, sizeof(o->variable) - strlen(o->variable) - 1); | ||||
| 						strncat(o->variable, "|", sizeof(o->variable) - strlen(o->variable) - 1); | ||||
| @@ -182,6 +192,21 @@ static int apply_outgoing(struct outgoing *o, char *fn, FILE *f) | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static void safe_append(struct outgoing *o, time_t now, char *s) | ||||
| { | ||||
| 	int fd; | ||||
| 	FILE *f; | ||||
| 	fd = open(o->fn, O_WRONLY|O_APPEND); | ||||
| 	if (fd > -1) { | ||||
| 		f = fdopen(fd, "a"); | ||||
| 		if (f) { | ||||
| 			fprintf(f, "%s: %d (%ld) (%ld)\n", s, o->retries, (long)ast_mainpid, (long) now); | ||||
| 			fclose(f); | ||||
| 		} else | ||||
| 			close(fd); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void *attempt_thread(void *data) | ||||
| { | ||||
| 	struct outgoing *o = data; | ||||
| @@ -201,6 +226,9 @@ static void *attempt_thread(void *data) | ||||
| 			/* Max retries exceeded */ | ||||
| 			ast_log(LOG_EVENT, "Queued call to %s/%s expired without completion after %d attempt(s)\n", o->tech, o->dest, o->retries - 1); | ||||
| 			unlink(o->fn); | ||||
| 		} else { | ||||
| 			/* Notate that the call is still active */ | ||||
| 			safe_append(o, time(NULL), "EndRetry"); | ||||
| 		} | ||||
| 	} else { | ||||
| 		ast_log(LOG_NOTICE, "Call completed to %s/%s\n", o->tech, o->dest); | ||||
| @@ -234,23 +262,32 @@ static int scan_service(char *fn, time_t now, time_t atime) | ||||
| 		f = fopen(fn, "r+"); | ||||
| 		if (f) { | ||||
| 			if (!apply_outgoing(o, fn, f)) { | ||||
| 				/* Increment retries */ | ||||
| 				o->retries++; | ||||
| #if 0 | ||||
| 				printf("Retries: %d, max: %d\n", o->retries, o->maxretries); | ||||
| #endif | ||||
| 				if (o->retries <= o->maxretries + 1) { | ||||
| 					/* Add a retry line at the end */ | ||||
| 					fseek(f, 0L, SEEK_END); | ||||
| 					fprintf(f, "Retry: %d (%ld)\n", o->retries, (long) now); | ||||
| 					fclose(f); | ||||
| 				if (o->retries <= o->maxretries) { | ||||
| 					if (o->callingpid && (o->callingpid == ast_mainpid)) { | ||||
| 						ast_log(LOG_DEBUG, "Delaying retry since we're currently running '%s'\n", o->fn); | ||||
| 					} else { | ||||
| 						/* Increment retries */ | ||||
| 						o->retries++; | ||||
| 						/* If someone else was calling, they're presumably gone now | ||||
| 						   so abort their retry and continue as we were... */ | ||||
| 						if (o->callingpid) | ||||
| 							safe_append(o, time(NULL), "AbortRetry"); | ||||
| 							 | ||||
| 						/* Add a retry line at the end */ | ||||
| 						fseek(f, 0L, SEEK_END); | ||||
| 						fprintf(f, "StartRetry: %d %d (%ld)\n", ast_mainpid, o->retries, (long) now); | ||||
| 						fclose(f); | ||||
| 						launch_service(o); | ||||
| 					} | ||||
| 					/* Update the file time */ | ||||
| 					tbuf.actime = atime; | ||||
| 					tbuf.modtime = now + o->retrytime; | ||||
| 					if (utime(o->fn, &tbuf)) | ||||
| 						ast_log(LOG_WARNING, "Unable to set utime on %s: %s\n", fn, strerror(errno)); | ||||
| 					now += o->retrytime; | ||||
| 					launch_service(o); | ||||
| 					return now; | ||||
| 				} else { | ||||
| 					ast_log(LOG_EVENT, "Queued call to %s/%s expired without completion after %d attempt(s)\n", o->tech, o->dest, o->retries - 1); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user