Compare commits

..

374 Commits

Author SHA1 Message Date
Kevin P. Fleming
3c00fa343f Convert all release tags to Opsound music-on-hold.
For more details:
http://blogs.digium.com/2009/08/18/asterisk-music-on-hold-changes/



git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/1.2.7@212958 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-08-18 20:42:51 +00:00
Kevin P. Fleming
c22cac6853 importing files for 1.2.7 release
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/1.2.7@19610 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-12 22:34:11 +00:00
Kevin P. Fleming
f295815c45 Creating tag for the release of asterisk-1.2.7
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/1.2.7@19609 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-12 22:31:05 +00:00
Tilghman Lesher
829bf52765 Bug 6490 - telco intercept should report NOANSWER instead of CHANUNAVAIL
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@19397 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-11 22:39:59 +00:00
Tilghman Lesher
b224ed93ca Bug 6061 - Fix ODBC storage of VM on PGSQL and MSSQL
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@19394 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-11 22:24:46 +00:00
Kevin P. Fleming
c3d195a2b3 don't create a 'voicemail' symlink in the sounds directory; app_voicemail has not needed it since January of 2005 (issue #6613)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@19353 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-11 21:58:47 +00:00
Tilghman Lesher
aea2d73afa Bug 6097 - possible descriptor leak
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@19351 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-11 21:55:51 +00:00
Kevin P. Fleming
5bc6b3b6fd don't call the originating device as part of the Page() operation (issue #6932)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@19348 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-11 21:50:18 +00:00
Kevin P. Fleming
58c3bdc8f1 simplify spy queue flushing logic, and always force a flush when one side gets full, even if the other side is not empty (issue #6457)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@19347 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-11 21:35:52 +00:00
Kevin P. Fleming
6f7efa99d5 don't destroy the entire dialplan during 'reload', just atomically replace it like 'extensions reload' does (issue #6047)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@19345 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-11 21:14:42 +00:00
Joshua Colp
fb912bc629 Minor linked lists bug fix. When you're dealing with swapping entries around a lot it can cause a seg fault.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@19303 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-11 20:46:38 +00:00
Kevin P. Fleming
95dc3bba01 handle call time limit properly when warning is requested _after_ call would hae already ended (issue #6356)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@19301 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-11 20:11:01 +00:00
BJ Weschke
83b525e2cb When using the silence detector in ast_play_and_record() and ast_play_and_prepend(), the truncation code never gets called to remove the detected silence, because the value of res is zero when control gets to that point. #6903 w/some mods (softins)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@19008 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-11 01:05:01 +00:00
BJ Weschke
4a40420978 Don't say that we can pass an 'exten' argument in the documentation of Park() when we really cannot. #6902 (opsys)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@18866 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-10 17:29:51 +00:00
Tilghman Lesher
08cc142495 Bug 6914 - .txt file fails to rename on operator out
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@18494 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-08 19:20:45 +00:00
Tilghman Lesher
48d13f84a5 Bug 6913 - fix for possible buffer overflow
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@18436 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-07 22:07:38 +00:00
Olle Johansson
7b12d67e50 - Fix cause codes
- Add cause code for incompatible formats


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@18260 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-07 14:16:41 +00:00
Olle Johansson
d98317c7ad - Fix possible minor memory leak in chan_sip
- Return proper cause code on memory allocation error



git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@18250 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-07 13:47:32 +00:00
Kevin P. Fleming
ce8275960e fix typo
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@18089 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-06 22:15:20 +00:00
Kevin P. Fleming
a6e5c98723 small fix... don't try to check conference details if it couldn't be created or found
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@18088 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-06 22:09:54 +00:00
Kevin P. Fleming
60df6b45d2 don't try to support 'i' or 'r' options if chan_zap is not loaded, and warn the user when they attempt to use them (issue #6675)
update application help text to more clearly define when Zaptel and chan_zap are required


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@18087 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-06 22:04:58 +00:00
Russell Bryant
235212182e move continue out of block that checks verbose level (issue #6880)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@17945 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-06 17:24:25 +00:00
Joshua Colp
831a96aac1 Update email address to my Digium one
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@17905 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-06 17:00:10 +00:00
Joshua Colp
bdea273046 Unlock channel on failure so that ast_mutex_destroy doesn't throw a fit (issue #6647 reported by casper)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@17702 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-05 20:01:19 +00:00
Olle Johansson
f08096e951 Issue #6654: Enum crash on ADDRESS record, possibly bad record, but still a crash
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@17489 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-05 06:50:35 +00:00
Olle Johansson
d5a3b59ccf Issue #6878 - Unhide DNDstate manager events (thanks casper)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@17367 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-04 18:28:14 +00:00
Olle Johansson
457bdd22bb Issue #6882 - move "res=-1" out of verbosity block, minor code cleanups (casper)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@17335 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-04 17:59:18 +00:00
Matt O'Gorman
43fde6acce Adds documentation to show what the w flag.
Patch from Ian Kinner at Digium.


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@17283 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-04 15:24:50 +00:00
Olle Johansson
adf51ade80 Issue 6870 - document that parking lots need to be numeric
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@17150 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-03 20:38:11 +00:00
Olle Johansson
65f95fee51 Issue #6848 take two - Use the tag provided by the SUBSCRIBE request when sending NOTIFY
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@17147 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-03 20:22:21 +00:00
Olle Johansson
bca4868578 Ugly patch to avoid hangup causes in non-final responses
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@17074 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-03 17:49:17 +00:00
Russell Bryant
9a729f7aff move a NULL check to before the first time the pointer is dereferenced (issue #6832)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@16771 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-31 19:11:26 +00:00
Russell Bryant
d125a1a278 fix the situation where bindport is specified but bindaddr is not (issue #6616)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@16744 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-31 18:42:09 +00:00
Kevin P. Fleming
6c0ac0721e ensure that hint watchers (subscribers) cannot be added or removed while the dialplan is being modified
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@16742 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-31 18:24:22 +00:00
Tilghman Lesher
65acfca5af Bug 6853 - Manager fixes: 1) extra ActionID, 2) missing colon
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@16581 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-30 22:56:35 +00:00
Tilghman Lesher
3585625b40 Bug 6849 - trivial typo fix
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@16579 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-30 22:46:06 +00:00
Joshua Colp
c43f01c211 Add another check for 64-bit goodness (issue #6850 reported by evilbunny)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@16559 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-30 21:44:03 +00:00
Joshua Colp
52aa07e2b2 Do not exceed the array size for maximum allowed moh files. (issue #6842)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@16534 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-30 17:55:28 +00:00
Olle Johansson
b97c1529fc Set initial value on adsipark
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@16346 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-30 01:34:53 +00:00
Olle Johansson
0a48c19845 Typo fix.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@16344 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-30 01:28:41 +00:00
Olle Johansson
8aa27f2c5c Typo (Issue 6839, casper)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@16303 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-30 00:28:59 +00:00
Tilghman Lesher
0bb7b71572 Bug 6830 - Let GosubIf work with the same conditions as a GotoIf (change in API approved by Russell)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@16192 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-29 19:11:18 +00:00
Tilghman Lesher
ac1e4d72dd Bug 6835 - Updates to GotoIf help text
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@16082 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-29 14:10:23 +00:00
Russell Bryant
ecf158b51e tell unsetenv for solaris to return the result of the setenv call
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@16008 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-29 04:15:11 +00:00
Olle Johansson
8d417967ce Issue #6823
- Portability issue with the registration port number patch from yesterday.
  Be compatible with more systems than OS/X :-)
  Thanks Rizzo for the advice.


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@15898 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-29 00:58:49 +00:00
Kevin P. Fleming
8d1c316519 ensure that list traversal loops which skip entries properly update the 'previous entry' pointer so when entries _are_ removed the list does not get damaged
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@15896 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-29 00:32:10 +00:00
Russell Bryant
70bd3bebc5 backport astmm + sparch fixes from the trunk
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@15743 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-28 20:22:05 +00:00
Russell Bryant
8c63eaec22 fix Bus Error on sparc (issue #6354)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@15703 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-28 19:47:03 +00:00
Olle Johansson
35ea822831 Fix breakage of NAT support for peers with qualify=yes.
Thanks Damin for access to your system, sorry folks.


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@15699 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-28 19:07:34 +00:00
Russell Bryant
420f3d12aa fix the order in which for loops are expanded (issue #6810)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@15658 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-28 18:09:05 +00:00
Tilghman Lesher
469e6d539a Bug 6815 - Adding quotes to make bash happy
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@15615 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-28 17:48:18 +00:00
Olle Johansson
09bf0c3032 Issue #6736 - Use flags for OPTION messages. Thanks Casper!
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@15381 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-27 23:45:31 +00:00
Olle Johansson
3db3883d3d Issue #6597 - sip show registry shows incorrect port
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@15376 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-27 23:29:55 +00:00
Olle Johansson
b85f9ea8fb Issue #6409 - Use "s" extension when there's no username in the URI
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@15366 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-27 22:50:41 +00:00
Tilghman Lesher
84b4d40f79 Bug 6601 - More configuration abilities for the RH init script
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@14868 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-25 05:07:52 +00:00
Tilghman Lesher
ea4baa91d0 Fix incorrect size of zeroing (left over from when maxmsg was hardcoded at 100)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@14830 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-25 05:01:16 +00:00
Tilghman Lesher
eb76fca6a3 Bug 6783 - When context is specified, voicemail should look for mailboxes in that context
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@14821 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-25 04:09:04 +00:00
Russell Bryant
677ed9a31a use the correct variable in an error message (issue #6791)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@14704 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-24 14:48:11 +00:00
BJ Weschke
dea7edda6b Fix a typo in the app description
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@14659 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-24 04:53:42 +00:00
BJ Weschke
da3df5ec26 Doxygen comment typo corrections
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@14610 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-24 00:48:03 +00:00
Joshua Colp
0a0470ad00 Issue #6764 - Return BUSY signal when other party is busy at Attended Transfer (Reported by mnachev)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@14523 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-23 21:51:50 +00:00
Matthew Fredrickson
b89b296584 Fix SETUP_ACK handling so that we change channels if so requested
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@14522 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-23 21:44:36 +00:00
BJ Weschke
41feb1c7ff Bug #5884 - fix a possible race state in app_meetme when a channel has gone away and we are reading continuously for more frames. (mneuhauser)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@14467 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-23 20:43:05 +00:00
Russell Bryant
9884c9637a don't crash when asked to read from a file that doesn't exist (issue #6786)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@14462 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-23 20:13:48 +00:00
Joshua Colp
b0f4874196 Fix a minor code issue
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@14276 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-22 22:18:32 +00:00
Joshua Colp
3667b25224 Issue #6781 - Verbose levels not enforced in app_voicemail (Reported by flobi)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@14275 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-22 22:13:30 +00:00
Joshua Colp
dcccda229d Issue #5918 - Disposition showing FAILED even though call is answered successfully (Reported by tracinet)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@14234 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-22 21:38:32 +00:00
Joshua Colp
d31a0d9e7b Issue #6780 - ast_pbx_outgoing_cdr_failed description fix. (Reported and fixed by casper)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@14191 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-22 20:59:21 +00:00
Olle Johansson
674425a343 Issue #6766 - fix ;user=phone functionality. (Reported by alein, fix by russell - thanks!)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@14140 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-22 09:10:13 +00:00
Russell Bryant
efd60d1d1f add a note explaining how to set the DYNAMIC_FEATURES variable to allow the use
of custom features (issue #6747)


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@13964 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-21 18:59:29 +00:00
Russell Bryant
0cfcb22bbc fix crash when using the ParkAndAnnounce application. When using this application,
there will be no peer channel to play the parking announcement to. (issue #6756)


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@13961 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-21 18:21:47 +00:00
Russell Bryant
9925080ca6 fix REGEX on strings that contain quotes (issue #6678)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@13925 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-21 17:45:56 +00:00
Russell Bryant
e34983cde0 fix spelling of whiskey
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@13888 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-21 16:22:16 +00:00
Russell Bryant
17187101f6 don't add conference participant if the user hangs up while recording their name (issue #6661)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@13851 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-21 15:53:27 +00:00
Russell Bryant
747495fc0e re-add the Account parameter to the sample call file since it's not really
deprecated since the CDR function is no longer built in


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@13814 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-21 14:20:28 +00:00
Tilghman Lesher
d564b81083 Bug 6714 - Workaround to avoid retrieving incomplete voicemail message
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@13748 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-21 06:24:56 +00:00
Tilghman Lesher
50249c732b Do away with some warnings and fix some indentation
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@13707 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-21 05:27:33 +00:00
Olle Johansson
108275cf6c Do not overwrite ANI if it's set by IE (sendany=yes in the peer)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@13634 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-20 17:36:45 +00:00
Russell Bryant
13b57f8255 revert the change made in revision 12927 in favor of keeping the original
behavior of the option.  The documentation has now been updated to reflect
the actual behavior.  (issue #6523)


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@13550 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-19 09:59:55 +00:00
Olle Johansson
6b8f2a96f1 Reset global_rtautoclear at sip reload
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@13547 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-19 09:25:09 +00:00
Tilghman Lesher
b21dc2c0c2 Bug 6737 - Fix compile warning on OS X
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@13279 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-16 20:05:00 +00:00
Olle Johansson
f096152b20 Issue #6690 - clarify progressinband default setting
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@13239 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-16 17:58:54 +00:00
Russell Bryant
3b776cdfdc always use the callerid signalling method set in the zt_pvt strucutre as
opposed to the last one read from the config file (issue #6734, with mods)


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@13237 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-16 17:42:46 +00:00
Olle Johansson
9593aa0aa1 To quote giant developers: "Oops". Thanks, Tony!
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@13197 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-16 06:56:20 +00:00
Russell Bryant
4edd97a713 - remove some calculations that will always result in 0
- if a CDR was never started, don't try to calculate a duration and consider it failed


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@13161 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-15 22:16:15 +00:00
Tilghman Lesher
eb1b6f313e Reverting patch from bug 6667
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@13095 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-15 18:07:06 +00:00
Olle Johansson
38ca23948d Issue #6728: Remove parameters to Event: header on SUBSCRIBE requests
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@13026 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-15 13:01:23 +00:00
Russell Bryant
e6ae8990bc when using the G() option to Dial, fix sending the called channel to 1 priority
beyond what was specified (issue #6523)


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@12927 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-14 18:41:05 +00:00
Russell Bryant
14e8c4c5a3 fix a problem with not loading realtime queue members by always reloading a
realtime queue from the database even if it is found in the list (issue #6680)


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@12925 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-14 18:28:39 +00:00
Tilghman Lesher
b2bd6c27db Bug 6667 - Fix for RFC2833 issues
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@12792 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-13 15:28:35 +00:00
Russell Bryant
d3080cc1ae add locking to protect the list of global dialplan variables
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@12646 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-12 19:26:27 +00:00
Olle Johansson
023a312f65 Set properties on two files that lacked properties for eol etc
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@12613 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-12 18:54:31 +00:00
Russell Bryant
89995395d9 fix build on parisc (issue #6704)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@12577 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-12 17:57:37 +00:00
Olle Johansson
fbe6931218 Issue #5937 - Make sure SIP CANCEL's are re-transmitted
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@12495 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-10 12:13:51 +00:00
Olle Johansson
8545a6d4c0 Issue #6576 - SIP_CODEC not used for early media (reported by gpapadop73)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@12477 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-09 17:00:36 +00:00
Olle Johansson
3388661f38 Issue #6657 - Ignore 183 session progress without SDP
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@12458 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-08 10:51:47 +00:00
Tilghman Lesher
1d58eff4a7 Bug 6020 - Race condition where packet could be lost if first packet on list is acked
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@12195 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-07 00:05:27 +00:00
Tilghman Lesher
cc4595f85e Bug 6664 - More fixes for Solaris
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@12161 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-06 23:03:54 +00:00
Olle Johansson
ac9f562712 Revert earlier change
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@12072 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-06 14:23:14 +00:00
Olle Johansson
b3af62dc4f Fix for astmm compilation
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@12036 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-06 11:03:46 +00:00
Russell Bryant
a70900ccd0 fix a typo in the description of the ringtimeout option
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@11946 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-06 02:32:35 +00:00
Olle Johansson
782eb432ab Clear page2 flags at reload too
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@11849 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-05 12:40:10 +00:00
BJ Weschke
4e3b9d6389 Substitute variables in the post_process string (if it exists) before those variables could possibly disappear (channel hangup) #6462
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@11778 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-04 11:45:37 +00:00
Tilghman Lesher
dbc0f5d2e2 Bug 6638 - Solaris is starting to remind me of RedHat...
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@11715 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-03 17:13:37 +00:00
Olle Johansson
ea27f3c186 Change of URL
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@11659 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-03 08:12:33 +00:00
Tilghman Lesher
2dc23188a2 Bug 6638 - Use POSIX command for Solaris
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@11635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-03 00:38:14 +00:00
Tilghman Lesher
a4725e9c73 Bug 6638 - Change from a historic BSD command to a POSIX command for determining username
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@11634 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-03 00:34:52 +00:00
Tilghman Lesher
575c2bccd5 Bug 6637 - Fixes for Solaris
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@11609 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-02 22:26:30 +00:00
Tilghman Lesher
2d5cc8be5c If debugging, the frame pointer is helpful
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@11607 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-02 22:19:52 +00:00
Russell Bryant
10191fe126 fix inaccurate ack message to ChangeMonitor action (issue #6630)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@11561 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-02 19:05:40 +00:00
Russell Bryant
4a391da1bd make the terminology used in the synopsis match the option description
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@11530 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-02 06:16:26 +00:00
Russell Bryant
86406e8ba0 add the -L option to the synopsis on the man page
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@11528 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-02 06:11:53 +00:00
Tilghman Lesher
536dcc2058 Bug 6615 - Fix 64bit conversion errors by using a long int
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@11503 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-01 17:41:52 +00:00
Tilghman Lesher
c4c44af8e3 Bug 6618 - Solaris compatibility fix
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@11479 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-01 06:39:10 +00:00
Russell Bryant
b26f150b75 fix the output that indicates whether qualify smoothing is on or not (issue #6608)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@11410 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-28 19:46:04 +00:00
Russell Bryant
271ccecaf2 adjust the keys directory when astvarlibdir is specified in asterisk.conf (issue #6602)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@11408 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-28 19:31:10 +00:00
Russell Bryant
0742e08800 add a missing newline in the agi app description (thanks wunderkin!)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@11382 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-28 18:31:04 +00:00
Russell Bryant
34a135da3b don't try to print the help text for a CLI command when RESULT_SHOWUSAGE is
returned if there is no help text available (issue #6604)


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@11281 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-27 15:20:48 +00:00
Russell Bryant
39139b2802 fix finding realtime peers that are not dynamic by ip address (issue #6093)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@11279 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-27 15:14:53 +00:00
Russell Bryant
799247b4d5 don't hang up the channel if its state is set to UP before we return from ast_call (issue #6569)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@11250 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-27 02:50:09 +00:00
Tilghman Lesher
677a22c209 Bug 5950 - reenable queue log rotation; also, eliminate redundant code
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@11165 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-26 16:26:39 +00:00
Matthew Fredrickson
973a1dec88 Backport of fix to translation optimizations. Thanks again file!
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@11120 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-25 19:54:40 +00:00
Kevin P. Fleming
dfc0e65f4b factor the number of translation steps required into translation path decisions, so that equal cost paths that require fewer translations are preferred
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@11089 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-25 05:08:46 +00:00
Kevin P. Fleming
1e94621214 reformat code to fit guidelines
remember which translation paths are multi-step paths


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@11062 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-25 04:59:50 +00:00
Kevin P. Fleming
5fbe407b98 ensure that spy frame queueing is able to deal with translation failing for any reason (issue #6546)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@11058 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-25 04:23:48 +00:00
Tilghman Lesher
a3ce65e5cd Oops, this was broken in 1.2, too.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@10952 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-23 23:06:42 +00:00
Kevin P. Fleming
fcf8040825 backport list handling fix from trunk (solves memory leak problem in cdr variables and device state watchers)
remove unusued variable to silence compiler warning


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@10863 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-23 14:57:53 +00:00
Kevin P. Fleming
842e9246a6 add comment warning people about trying to use hostnames/IPs in the sample config
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@10736 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-22 17:32:15 +00:00
Tilghman Lesher
6b682d34ff Would be nice to tell people to look in the right file to increase a constant
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@10577 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-20 23:01:12 +00:00
Mark Spencer
1ef0003131 Handle ACKing properly (remove gratuitous -1)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@10535 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-20 06:17:26 +00:00
Mark Spencer
4e884dbd28 Fix numerous places in jitter buffer where freed memory is referenced
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@10511 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-20 05:54:10 +00:00
Tilghman Lesher
0a1d8918d8 Okay, fseek doesn't return an offset
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@10487 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-19 18:29:16 +00:00
Tilghman Lesher
3da520e492 Fix possible lack of initialization of useadsi
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@10464 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-19 17:26:31 +00:00
Tilghman Lesher
0a0cf51877 Bug 6539 - Division by two negates error flag
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@10462 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-19 17:11:02 +00:00
Tilghman Lesher
cab988b595 Bug 6529 - memory leak in ast_play_and_prepend
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@10409 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-18 00:17:09 +00:00
Russell Bryant
507c47ffa4 fix incorrent index calculation for jitterbuffer history (issue #6517)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@10368 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-17 01:55:10 +00:00
Russell Bryant
7c92ffe150 when executing the Directory application from voicemail and a context is not
specified, use the "default" context, not the channel's current context (issue #6507)


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@10301 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-16 18:07:52 +00:00
Kevin P. Fleming
f522e07cbd ensure that agents logged in via the manager interface are stored in the persistence database (related to issue #6301)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@10137 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-15 01:21:33 +00:00
Kevin P. Fleming
df18b234b1 handle longer ENUM lookup results (issue #6476)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@10110 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-15 00:46:18 +00:00
Kevin P. Fleming
7652fdda20 ensure that FastAGI launcher can handle system call interruption (issue #6449)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@10108 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-15 00:36:57 +00:00
Matt O'Gorman
bab77bbab1 bug fix from 6485 with musiconhold not being turned
off by app_meetme


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@10021 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-14 20:56:41 +00:00
Kevin P. Fleming
ce008d40a1 don't double-increment abandon counter for calls that are hung up while dialing members (issue #6289)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@10018 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-14 20:20:15 +00:00
Mark Spencer
710445b5b1 Fix stopstream in menus (bug #6137)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@9990 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-14 19:11:25 +00:00
BJ Weschke
ba001a7d15 #ifdef the include too.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@9964 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-14 18:50:42 +00:00
BJ Weschke
4f144aa5e3 #ifdef'd the prctl fix to only try and compile on linux systems. Thanks rizzo for pointing this out.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@9961 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-14 18:45:34 +00:00
Kevin P. Fleming
8d66f50877 when answering INVITE, don't send codecs the peer didn't offer (issue #6052)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@9958 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-14 18:30:10 +00:00
Kevin P. Fleming
e0db36550e revert yesterday's temporary fix for issue #6052
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@9953 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-14 18:23:13 +00:00
BJ Weschke
13f4e66b14 Fixed my silly backport error from r9861
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@9870 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-14 04:45:14 +00:00
BJ Weschke
ae8fe3738b Merged changes from r9844 from /trunk. Make sure that PR_SET_DUMPABLE is set to make certain that we still dump core if Asterisk has setuid'd to run as non-root.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@9861 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-14 03:08:17 +00:00
Kevin P. Fleming
b5111fb985 don't try to use peer's dynamic codec numbers, it leads to duplication (issue #6052)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@9818 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-14 00:46:00 +00:00
Josh Roberson
671cde62de Don't set the formats before we stop indications. (issue #6380)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@9756 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-13 17:37:53 +00:00
Russell Bryant
0ea76a52a9 fix memory leak from not destroying the scheduler context on module unload
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@9609 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-11 19:23:20 +00:00
Russell Bryant
db467378b4 fix due to CDR changes
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@9607 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-11 19:16:23 +00:00
Russell Bryant
e27d844918 now that CDR is a loadable module, don't depend on it elsewhere (issue #6460)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@9581 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-11 18:15:00 +00:00
Kevin P. Fleming
3b0edd5cfe clean up my mess from thread-starting change
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@9528 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-11 15:22:55 +00:00
BJ Weschke
74eef60486 kpfleming's fix from r9472 backported to 1.2
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@9493 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-11 06:29:34 +00:00
Kevin P. Fleming
b3a8fbf495 don't create monitor threads in detached mode, when we need to be able to pthread_join() them later if the module is unloaded (solve crash-on-unload problem for these channel modules)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@9404 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-10 20:38:59 +00:00
Tilghman Lesher
bae6e7b617 Revert behavior change from previous commit (fixes only)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@9326 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-09 21:10:10 +00:00
Tilghman Lesher
cf015dbefc Backport 5929 to 1.2
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@9323 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-09 21:02:05 +00:00
Russell Bryant
32cc1bedc1 add another location for postgresql headers (issue #6419)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@9262 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-09 02:31:21 +00:00
Russell Bryant
a96ecb64a6 reload peercontext on iax2 reload (issue #6442)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@9246 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-09 01:24:55 +00:00
Tilghman Lesher
d1757b3b49 Leave it to RH/CentOS to put the freetds headers in a completely nonstandard location.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@9233 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-08 22:34:38 +00:00
Matt O'Gorman
917259bcd3 Make logger report error,warning,notice if logger.conf
not found, also updated chan_oss to give correct
error message if its config file is not found.


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@9232 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-08 22:12:34 +00:00
Tilghman Lesher
eb177856db Bug 6176 - Fix race condition
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@9156 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-05 17:10:19 +00:00
Kevin P. Fleming
9849ad993d don't override ASTERISKVERSIONNUM to 000000 for non-svn builds
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@9086 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-02 18:37:04 +00:00
Matthew Fredrickson
bb886dd488 Fix for (#6309), potential (highly unlikely) memory leak in res_odbc
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@9073 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-02 16:12:13 +00:00
Kevin P. Fleming
48fb967c05 disable buggy PRI user-user code until it can be fixed
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8905 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-30 17:08:28 +00:00
Olle Johansson
e74a7116e5 Issue 6182 - Don't remove scheduled event until it's really done.
(reported by malverian) 


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8808 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-28 13:52:15 +00:00
Olle Johansson
fd25b81993 Issue 6362 - Register without Contact: and Expires: fails (reporter: op)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8785 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-27 08:02:16 +00:00
Tilghman Lesher
dcd9d8d58f Bug 6072 - Revisions to the source bison and flex files don't auto-regenerate these files
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8758 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-27 00:52:12 +00:00
Russell Bryant
1d9b2a9df1 fix problem with dtmf on e&m (issue #6364)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8729 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-26 19:42:35 +00:00
Olle Johansson
659da47b95 Issue 5898: Registrations does not get deleted if there's an active SIP dialog
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8710 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-26 14:39:36 +00:00
Russell Bryant
e83bfee678 don't call ast_update_realtime with uninitialized variables if we get a
registration with an expirey of 0 seconds (issue #6173)


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8677 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-25 19:14:43 +00:00
Russell Bryant
ab209c7d92 fix memory leak (inspired by issue #6351)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8666 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-25 18:39:44 +00:00
Olle Johansson
dc08bd8501 Issue #6439 - the "timebomb" bug. Patch by Markster over GPRS
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8632 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-25 09:46:43 +00:00
Russell Bryant
aca3c1f79d don't leak almost 200 bytes for each new channel (issue #6330)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8619 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-25 05:38:36 +00:00
Kevin P. Fleming
e07c977f18 ensure hangup cause code is handled properly when channel does not return a frame (issue #6346)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8608 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-25 01:50:52 +00:00
Russell Bryant
2ae21cc5c3 completely arbitrary whitespace change for testing something with svnmerge ...
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8600 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-24 22:55:32 +00:00
Kevin P. Fleming
05fed23d06 ensure that channel cannot become zombie after we check but before we try to start indications
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8588 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-24 22:32:09 +00:00
Matthew Fredrickson
2f43722570 Backport fix for #6229, hangup on polarity reversal
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8573 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-24 20:37:30 +00:00
Olle Johansson
7ea315539c Issue 6114: Don't hangup on BYE/ALSO with no channel.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8562 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-24 19:21:15 +00:00
Olle Johansson
10d527906a Issue #6308 - never send response to ACK. (Reported by whiskerp)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8537 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-24 13:15:13 +00:00
Russell Bryant
2f1d118537 fix memory leak from not freeing the queue member list when freeing an old queue
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8445 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-22 19:03:53 +00:00
Russell Bryant
696922defe fix MixMonitor crash (issue #6321, probably others)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8437 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-22 17:47:13 +00:00
BJ Weschke
cea50c9247 Bug fix: Correct some scenarios where CALL_LIMIT could not be getting adjusted properly allowing chan_sip to send calls when it really shouldn't. Bug #6111
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8433 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-22 15:13:41 +00:00
Tilghman Lesher
636f956bf0 Bug 6281 - Cannot set more than a single header with SIPAddHeader
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8429 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-22 08:52:49 +00:00
Russell Bryant
64b1d91701 add a modified fix to prevent writing outside of the provided workspace when
calculating a substring (issue #6271)


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8418 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-22 02:05:41 +00:00
Russell Bryant
ff83f7c6ed temporarily revert substring fix pending the result of the discussion in issue #6271
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8414 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-21 23:43:14 +00:00
Russell Bryant
87c0cd2667 prevent the possibility of writing outside of the available workspace (issue #6271)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8412 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-21 23:17:06 +00:00
Tilghman Lesher
366c8a99ef Bug 5936 - AddQueueMember fails on realtime queue, if queue not yet loaded
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8394 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-21 18:29:39 +00:00
Russell Bryant
30f2aff526 fix invalid value of prev_q (issue #6302)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8347 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-20 18:34:42 +00:00
Matt O'Gorman
962cffffc7 solved problem with delayreject and iax trunking
bug 4291


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8320 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-20 01:00:46 +00:00
Olle Johansson
f196484187 Enable "musicclass" setting for sip peers as per the config sample.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8281 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-19 19:40:28 +00:00
Tilghman Lesher
c40fe2f71a Bug 6072 - Memory leaks in the expression parser
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8276 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-19 19:14:37 +00:00
Russell Bryant
74c149e891 fix Message-Account header to use the ip address if the fromdomain
isn't set (issue #6278)


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8242 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-19 04:56:48 +00:00
Russell Bryant
57c82eb66f fix a seg fault due to assuming that space gets allocatted on the stack in the
same order that we declare the variables (issue #6290)


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8232 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-19 04:17:45 +00:00
Matt O'Gorman
5460606cff Solves issue with the login proccess in meetme
patch from 6136


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8194 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-18 21:02:06 +00:00
Russell Bryant
1a509417a4 remove ChangeLog from the 1.2 branch. It will only be present in the tags.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8173 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-18 02:49:21 +00:00
Matt O'Gorman
898cd20ceb Changed order of autoload so that pbx_ comes before
channels, and in doing so cause bug 6002 to not
be an issue


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8162 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-18 00:47:04 +00:00
Matt O'Gorman
792b78b317 Stop any generators running on a channel when
festival is called as described in 5996


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8140 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-17 20:10:29 +00:00
Matthew Fredrickson
4efe647169 Backport of fix for #6094
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8134 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-17 18:29:57 +00:00
Matt O'Gorman
4fbba55f14 Fixed code ordering of logger_init and queue_log_init
bug 6263


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8124 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-17 16:55:30 +00:00
Kevin P. Fleming
2efc5a9e83 update CLI copyright notice
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8122 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-17 13:11:55 +00:00
Kevin P. Fleming
57144d5102 do rlimit check _after_ reading config file, in case 'dumpcore' is specified there
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8112 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-16 23:51:37 +00:00
Tilghman Lesher
555bbffec3 Bug 6238 - Fix segfault when delimiter not specified
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8074 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-14 19:06:44 +00:00
Russell Bryant
e22510658b fix spelling errors (issue #6227)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@8047 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-13 06:07:39 +00:00
Tilghman Lesher
cb08e49303 Bug 6211 - Add option deletevoicemail as equivalent to option delete for Realtime
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7999 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-12 06:14:22 +00:00
Russell Bryant
dee03d2b80 move variable to correct scope (issue #6197)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7986 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-11 19:08:53 +00:00
Russell Bryant
b5ec3e47fa fix temp greetings with ODBC storage (issue #6078)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7976 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-11 07:18:16 +00:00
Russell Bryant
ffb11fb950 fix mem leak on module unload (issue #6190)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7972 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-11 05:46:39 +00:00
Russell Bryant
fbee1f0ed7 don't override an error condition that occurred when acting on the primary channel
when stopping the autoservice on the peer channel.  (from issue #6087)


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7970 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-11 05:26:21 +00:00
Russell Bryant
131ada1116 lock list of translators *before* recalculating the translation matrix
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7965 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-11 04:53:24 +00:00
Matt O'Gorman
b0609b29aa Minor typo refrenced in 6191
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7963 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-11 04:38:07 +00:00
Russell Bryant
bbb59b8c5e fix locking error - lock instead of unlock
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7960 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-11 04:19:21 +00:00
Russell Bryant
72deed0c37 fix a little typo
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7957 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-11 03:12:44 +00:00
Tilghman Lesher
b9f8c60fa7 Bug 6192 - behave correctly when mailbox is specified as argument
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7955 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-11 01:30:10 +00:00
Olle Johansson
87b36e1ff1 - Adding reference to README.tds
- Reformatting table


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7939 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-10 08:48:14 +00:00
Kevin P. Fleming
d8c5d338cb re-initialize _all_ sequence numbers when transfer completes
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7917 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-09 22:48:48 +00:00
Russell Bryant
417438fea0 add missing unlock (issue #6112)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7915 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-09 22:07:26 +00:00
Tilghman Lesher
5488ffb6d4 Bug 6157 - Memory leak
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7908 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-09 20:08:24 +00:00
Tilghman Lesher
e8725ce940 Update variable documentation to match the code
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7904 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-09 18:37:50 +00:00
Kevin P. Fleming
0e734920e8 commit user/group-related changes from trunk
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7900 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-09 18:11:23 +00:00
Kevin P. Fleming
ad598a2060 backport fix from revision 7856 of trunk
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7899 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-09 18:09:53 +00:00
Kevin P. Fleming
bb47f95262 fix breakage introduced in revision 7871
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7898 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-09 18:08:07 +00:00
Russell Bryant
a7a2115b9c fix seg fault when using greek syntax in VoicemMailMain (issue #6142)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7871 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-09 05:11:44 +00:00
Russell Bryant
18429f2a69 backport fix for unnecessary unlock (issue #6171)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7870 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-09 04:52:16 +00:00
Tilghman Lesher
7e6430787c Bug 6156 - catch all threading errors, not just simple failure
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7848 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-07 07:27:18 +00:00
Tilghman Lesher
dc3ba8c223 Dumb error messages - "Context 'context' already included in 'in' context"
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7831 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-06 00:34:40 +00:00
Kevin P. Fleming
2fd6520a7e update agent persistence when an agent gets logged off by autologoff
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7829 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-06 00:21:00 +00:00
Tilghman Lesher
7a61b36104 Bug 6076 - Fix documentation of ast_trim_blank return value
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7827 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-05 23:53:07 +00:00
Kevin P. Fleming
2f4783a770 eliminate rounding errors that caused call time limits to be inaccurate (issue #5913)
round 'time left' reported during call limit warnings up to sound more accurate


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7825 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-05 23:49:50 +00:00
Tilghman Lesher
6056391a78 Bug 6081 - fix for memory leak, formatting fixes
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7823 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-05 23:07:08 +00:00
Kevin P. Fleming
213b3575ce ensure that variable is initialized
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7819 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-05 20:52:38 +00:00
Olle Johansson
3821e18d08 Fix copyright of changed file
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-05 09:13:21 +00:00
Kevin P. Fleming
224c6e3f7c send device state updates for auto-logoff of agents as well
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7809 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-05 00:58:29 +00:00
Kevin P. Fleming
18ab6f429c doh... fseek() has no useful return value
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7807 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-05 00:18:46 +00:00
Kevin P. Fleming
07f8542ce7 use proper fwrite() parameters and return value
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7805 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-04 23:51:03 +00:00
Kevin P. Fleming
cf293c224d return properly after extending file
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7803 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-04 23:45:34 +00:00
Kevin P. Fleming
e234ad0011 ensure that ulaw/alaw sound files are filled with silence when extended (not zeroes)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7800 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-04 23:27:57 +00:00
Kevin P. Fleming
229b778b0b make monitoring more tolerant of peers that deliver frames in bursts
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7799 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-04 23:02:38 +00:00
Olle Johansson
66f484defe Issue #5980: Removing extra CR+LF in manager events - needs port to trunk
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7795 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-04 21:46:40 +00:00
Olle Johansson
ed523e248a Fixing typo in XML for video updates.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7792 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-04 21:43:14 +00:00
Russell Bryant
3c49f27bf4 use a more correct way of determining the size of the destination buffer
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7773 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-04 07:06:50 +00:00
BJ Weschke
226d146b25 Fix the 'if' clause to be true under the right conditions. Bug #6126
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7771 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-04 05:27:38 +00:00
Kevin P. Fleming
1892289329 remove unused 'old' expression parser
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7746 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-03 20:22:18 +00:00
Tilghman Lesher
5529fc0355 Bug 6121 - typo in application description
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7743 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-03 18:15:12 +00:00
Kevin P. Fleming
73ef559240 revert incorrect fix for bug #6048 from revision 7709
put in correct (simpler) fix
add doxygen docs for channel spy 'state' values


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7740 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-03 17:24:56 +00:00
Kevin P. Fleming
b59a63c8cd backport rport scanning fix from trunk (bug #6071)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7738 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-03 17:00:01 +00:00
Kevin P. Fleming
c36927137f don't leak memory for (most) expression evaluations
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7736 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-03 16:34:12 +00:00
Tilghman Lesher
649aaad100 Bug 6084 - MixMonitor after a 'cli stop monitor' deadlocks
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7709 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-02 07:31:54 +00:00
BJ Weschke
ea4c262482 Fix compiler warnings.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7706 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-02 02:04:14 +00:00
Tilghman Lesher
89de6c9df6 Bug 6091 - Fix race condition around uniqueid
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7677 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-30 14:54:19 +00:00
Russell Bryant
4578bc3b0c fix memory leak in build_rpid (issue #6070)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7665 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-28 17:35:56 +00:00
Russell Bryant
8df1e4866a backport fix for permissions of created recordings (issue #6067)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7663 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-27 21:07:08 +00:00
Kevin P. Fleming
9f92220a9c backport fix to ensure that DSP is never enabled on pseudo channels
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7641 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-27 00:07:45 +00:00
Tilghman Lesher
09a9e7bcb7 Remove copy of code in libc, preferring code in utils.c (public domain code)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7637 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-26 20:32:50 +00:00
Russell Bryant
a434f8877a cast time_t to an int in printf/scanf (issue #5635)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7634 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-26 18:19:12 +00:00
Tilghman Lesher
ef891dc0a7 Bug 6051 - VMCOUNT should work as documented and count all, not quit after finding 1
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7608 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-23 06:38:08 +00:00
Kevin P. Fleming
3ebe29c983 add license reference to copyright notice displayed when CLI session begins
add 'show warranty' and 'show license' CLI commands (still need a complete list of non-GPL components included in Asterisk)


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7606 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-23 03:01:24 +00:00
BJ Weschke
1028e43464 Another app documentation tweak.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7605 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-23 00:00:11 +00:00
Tilghman Lesher
4979f66f28 Bug 6050 SQL requires the use of single ticks to delimit values, not quotes
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7601 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-22 22:04:13 +00:00
Russell Bryant
a5e9fe97c8 revert changes to videosupport to allow per-peer setting, since it isn't quite
complete and there is not an obvious fix at this point


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7599 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-22 20:36:47 +00:00
Russell Bryant
2293cfaf84 remove stray unlock (issue #5955)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7595 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-22 16:17:43 +00:00
Josh Roberson
d252dde933 Actually put in the per-peer settings for sip video, as they didn't make it in at astricon somehow, and I've been too busy up until now to redo it.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7586 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-21 22:23:39 +00:00
Tilghman Lesher
37a49a5992 Allow a chan_alsa that failed to open sound devices to be unloaded.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7582 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-21 20:01:16 +00:00
BJ Weschke
2783801610 Bug #6040 - Documentation correction
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7580 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-21 19:53:49 +00:00
Tilghman Lesher
82f19c9a91 Bug 5777 - Remove parentheses on Goto in AEL, so that it parses correctly
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7577 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-21 19:23:12 +00:00
Russell Bryant
71d9531e45 check array bounds when parsing arguments to AGI (issue #5868)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7557 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-20 20:21:26 +00:00
Russell Bryant
3bbeaefa57 backport fix for reloading peer context (issue #6007)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7552 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-20 18:05:45 +00:00
Russell Bryant
4611be805a backport fix for segfault on directed pickup when no CDR is available (issue #5998)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7550 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-20 17:34:00 +00:00
Kevin P. Fleming
587493fdfc backport fix for larger-than-20ms-frames from trunk (bug #5697)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7546 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-20 12:58:37 +00:00
Russell Bryant
50079144e3 I messed up and accidently committed this to the trunk first ...
- add note on required values of sip_methods struct
- remove duplicate function prototype
- remove duplicate ast_mutex_lock (issue #6025)


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7529 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-19 23:47:23 +00:00
Tilghman Lesher
2ca80e76a0 Bug 5988 - record append option not working
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7523 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-19 19:06:46 +00:00
Tilghman Lesher
68e6502484 Bug 6026 - segfault for the sequence NoCDR(), SetAMAFlags()
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7521 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-19 05:38:44 +00:00
Tilghman Lesher
1e91dfa5df Document that curley braces must be on the same line as the keyword.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7519 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-17 18:55:38 +00:00
Tilghman Lesher
e4e5f7c65b Bug 6009 - off by one error
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7517 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-17 17:19:32 +00:00
Kevin P. Fleming
8ef66261f1 Max-Forwards headers must only be present on requests, not responses
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7515 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-17 03:59:05 +00:00
Kevin P. Fleming
90812b536c forcibly expire previous subscriptions from a peer when they resubscribe (keeps them from building up and waiting for expiration, and stops us sending unwanted NOTIFY messages to devices)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7513 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-17 03:44:30 +00:00
Kevin P. Fleming
2b880d3ef8 fix some buglet when building team branch version strings
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7510 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-17 02:20:04 +00:00
Tilghman Lesher
6ab729aeb3 We want to check the previous value, not the current value (which was just changed).
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7508 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-17 01:02:29 +00:00
Tilghman Lesher
c9f97f49c5 First field is truncated
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7497 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-16 00:49:39 +00:00
Christian Richter
8b352fcb94 * Added mISDN/mISDNuser Echo cancel Patch
* Fixed Makefiles so that chan_misdn can be compiled again
* added some hints, that mISDN cannot be compiled against gcc-4, SMP, Spinlock Debug
* fixed some Minor issues in chan_misdn, regarding Type Of Number and Presentation






git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7490 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-15 10:52:30 +00:00
BJ Weschke
5a06af4d57 Bug #6003 - Don't free the channel structure until after having sent the manager event.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7482 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-15 02:51:54 +00:00
Kevin P. Fleming
2ede900bfd clarify substring documentation
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7470 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-13 18:54:22 +00:00
Kevin P. Fleming
fb0ffc7784 correct broken math in tvfix() for timestamp values over one million
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7468 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-13 16:06:27 +00:00
Kevin P. Fleming
e69171dc06 restore ability of caller to hangup calls that are still ringing (issue #5839)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7453 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-13 05:53:00 +00:00
Kevin P. Fleming
8452f6b494 ensure that hangups while incoming calls are in early state are handled properly (issue #5919)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7451 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-13 05:14:27 +00:00
Kevin P. Fleming
f9bc6f8afc only report AGENT_IDLE for callback mode agents when they are actually idle (issue #5902)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7449 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-13 04:43:38 +00:00
Kevin P. Fleming
f9f44d7d9b use the stream's current point when pausing/unpausing, instead of elapsed time (which doesn't work when the stream has been skipped forward or backward) (issue #5897)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7448 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-13 04:25:14 +00:00
Kevin P. Fleming
86bb1472cc set all the child file descriptors to non-blocking so that we don't hang if the child fails to send a newline-terminated command or error message
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7435 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-12 17:30:59 +00:00
Tilghman Lesher
ef09c506c8 Typo
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7433 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-12 17:19:29 +00:00
Russell Bryant
af7b3b420e silence a couple of compiler warnings about pointer signedness
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7430 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-11 06:08:56 +00:00
Tilghman Lesher
3b80a35a66 Bug 5965 - major bug in AST_LIST_REMOVE
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7429 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-11 01:26:51 +00:00
Tilghman Lesher
f59b27258c Bug 5967
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7427 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-11 01:15:15 +00:00
BJ Weschke
d38fff38f9 Bug #5877
Make sure the digit string from E&M wink DNIS collection is properly null terminated as it grows.



git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7425 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-10 18:10:50 +00:00
Tilghman Lesher
91c5b12f25 Bug 5960
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7406 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-08 23:45:36 +00:00
Tilghman Lesher
894bdd5cda Documenting two keywords that were previously missing
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7404 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-08 23:32:08 +00:00
Kevin P. Fleming
d8c58ca6c8 initialize the buffer before using it...
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7386 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-08 01:05:43 +00:00
Kevin P. Fleming
43f7956422 ensure that hints are allowed to use global variable references
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7382 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-07 20:46:55 +00:00
Kevin P. Fleming
96fcc02900 ensure that sound/music files are handled as binary
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7351 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-06 00:23:05 +00:00
Kevin P. Fleming
2e8b6e7f20 replace with unmodified file
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7349 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-06 00:19:17 +00:00
Kevin P. Fleming
3ed93398e9 _really_ don't mess with line endings
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7347 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-06 00:08:19 +00:00
Kevin P. Fleming
d84e0caea8 don't try to expand keywords in this file
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7346 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-06 00:07:48 +00:00
Kevin P. Fleming
5c1da58b90 set this file to binary mode, so it won't be mangled on export/checkout
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7345 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-06 00:02:08 +00:00
Russell Bryant
018c617199 remove ASTERISKVERSIONNUM from the version string given to doxygen
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7340 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-05 06:47:51 +00:00
Russell Bryant
a49f954f6a don't delete dynamic queue members when reloading the static members from a realtime database (issue #5922)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7337 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-05 00:09:12 +00:00
Russell Bryant
03a8791440 fix the order of arguments to an error message (issue #5927)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7335 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-05 00:01:17 +00:00
Kevin P. Fleming
78ad17381e use a more efficient way to get the revision number, that will also report if the working copy contains uncommitted modifications
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7329 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-04 18:03:07 +00:00
Tilghman Lesher
5b03803e2f Bug 5925: check for "Unknown", as that's what app_voicemail puts into the field for Unknown callerid
Also, remove useless res checks (initialized to 0; never set)


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7310 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-03 19:55:05 +00:00
Olle Johansson
ee1e461a57 Documenting the default registerattempts setting as 0, continue hammering the server for ever and ever ;-)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7299 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-03 01:24:40 +00:00
Tilghman Lesher
a543725311 Turn on executable bits for startup scripts, and fix bash var interpolation for Mandrake
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7285 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-02 21:12:05 +00:00
Olle Johansson
8c701a0861 Bug #5907. Improve SIP INFO DTMF debugging output. (1.2 & Trunk)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7275 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-02 00:52:13 +00:00
Kevin P. Fleming
5fbe566524 inherit channel variables into channels created by Page() application (issue #5888)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7274 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-02 00:51:15 +00:00
Kevin P. Fleming
e14cf31bc9 allow previous context-searching behavior to be used if desired (issue #5899)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7273 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-02 00:42:40 +00:00
Kevin P. Fleming
0042c03c7e properly handle password changes when mailbox is last line of config file and not followed by a newline (issue #5870)
reformat password changing code to conform to coding guidelines (issue #5870)


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7272 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-02 00:39:00 +00:00
Kevin P. Fleming
41023ecb9c protect agent_bridgedchannel() from segfaulting when there is no bridged channel (issue #5879)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7271 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-02 00:28:48 +00:00
Kevin P. Fleming
fb8d0a544d allow variables to exist on both 'halves' of the Local channel (issue #5810)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7270 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-02 00:26:12 +00:00
Kevin P. Fleming
acaf8c9cc9 don't block waiting for the Festival server forever when it goes away (issue #5882)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7269 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-01 23:49:44 +00:00
Kevin P. Fleming
0d3fc8d103 ensure channel's scheduling context is freed (issue #5788)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7268 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-01 23:34:58 +00:00
Kevin P. Fleming
9bbfbacacc Makefile 'update' target now supports updating from Subversion repositories (issue #5875)
remove support for 'patches' subdirectory, it's no longer useful


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7266 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-01 23:18:29 +00:00
Olle Johansson
8e301c629f Changing bug report address to the Asterisk issue tracker
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7265 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-01 23:18:14 +00:00
Olle Johansson
9576d8a081 Removing references to 1.1dev, replacing with 1.2, in documentation files.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7263 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-01 22:21:13 +00:00
Olle Johansson
7db96672bf Fixing some spelling errors, as well as changing "cvs" to "subversion" in misdn documentation.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7261 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-01 21:38:38 +00:00
Kevin P. Fleming
0d8f099ca2 ensure that 'svn info' output is in the expected language for the script to parse (issue #5880)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7257 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-01 19:25:06 +00:00
Russell Bryant
0a4d7e5068 use ast_app_separate_args to split arguments (issue #5686)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7251 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-01 02:33:58 +00:00
Russell Bryant
a32f75b800 fix queue weight feature - compare member interfaces instead of pointers to
the members, since each queue has its own list of members. (issue #5863)


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7249 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-01 01:19:04 +00:00
Russell Bryant
78f37c51ef use '=' instead of '==' for string comparisons. /bin/bash is ok with this, but
/bin/sh is not.  (issue #5885)


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7247 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-01 00:44:34 +00:00
Russell Bryant
d6e5eb75ee remove outdated redhat init script and provide the updated one in 'make rpm' (issue #5786)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7244 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-30 21:31:18 +00:00
Russell Bryant
6f433a7e7b Comment out LD_ASSUME_KERNEL by default.
Print error messages if the asterisk executable or the asterisk configuration
directory are not found. (issue #5785, #5708)


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7242 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-30 21:24:52 +00:00
Russell Bryant
ce2ecb5582 fix DIALEDTIME when call has not been answered (issue #5862)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7234 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-30 17:39:36 +00:00
Russell Bryant
45c15e8561 do not allow an rtp message with zero type (issue #5749)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7233 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-30 14:27:59 +00:00
Russell Bryant
5e3f4186da fix hint case sensitivity (issue #5856)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7231 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-30 07:22:42 +00:00
Russell Bryant
d03694df19 add description of the "fromdomain" option (issue #5874)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7228 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-30 05:26:26 +00:00
Josh Roberson
d52e8fa7d2 backport fix from trunk
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7227 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-30 03:52:18 +00:00
Kevin P. Fleming
77c6cd0bff remove remaining CVS references
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7226 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-30 03:37:37 +00:00
Kevin P. Fleming
463ebe8b4b port memory leak fix from rev 7223 in trunk
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7224 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-30 03:20:42 +00:00
Kevin P. Fleming
a563eab49a remove extraneous svn:executable properties
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7221 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-29 18:24:39 +00:00
Kevin P. Fleming
bf9d4b103d do the multiple-lock check for cond_wait properly...
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7219 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-29 14:26:22 +00:00
Russell Bryant
7dc2449f3a print an error message if invalid arguments are specified
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7218 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-29 06:12:29 +00:00
Russell Bryant
27cc20db11 fix a couple of typos and a buglet
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7216 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-29 05:11:05 +00:00
Kevin P. Fleming
4e04f5f731 if the lock protected a pthread_cond is held recursively, warn before waiting onthe condition
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7213 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-29 01:25:28 +00:00
Kevin P. Fleming
5ec3844077 remove CVS ignore lists, set SVN ignore lists
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7212 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-29 00:46:54 +00:00
Kevin P. Fleming
f641c7cd0d port version string computation from trunk
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7208 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-28 04:01:06 +00:00
Kevin P. Fleming
49aa54cafc branch renames
remove unneeded branches


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7199 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-27 16:04:52 +00:00
Russell Bryant
e3b81e66a1 issue #5850
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7196 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-25 14:17:38 +00:00
Russell Bryant
7bb6b928b5 fix typo - thanks twisted :)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7194 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-23 06:02:32 +00:00
Russell Bryant
ad4dc7c4a9 fix the date
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7193 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-23 05:59:05 +00:00
Russell Bryant
feb9764721 issue #5828
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7191 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-23 05:57:10 +00:00
Russell Bryant
8c74501001 issue #5826
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7190 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-23 05:49:35 +00:00
Russell Bryant
5861d3fd64 issue #5829
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7189 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-23 05:43:27 +00:00
Kevin P. Fleming
08acdc6a86 backport fix from HEAD branch
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7186 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-21 19:34:09 +00:00
Kevin P. Fleming
3b50570c9b backport fix from HEAD branch
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7184 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-21 19:31:26 +00:00
Kevin P. Fleming
00d7e962a7 backport fix from HEAD branch
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7183 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-21 19:29:51 +00:00
Russell Bryant
192f7413c2 revert previous change for Darwin
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7174 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-21 15:57:51 +00:00
Russell Bryant
5bdb8074aa issue #5789
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7170 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-21 13:40:34 +00:00
Russell Bryant
6abe5e1b23 don't hardcode poll.o for Darwin
fix incorrect portion of yesterday's Solaris fixes


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7169 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-21 13:23:53 +00:00
Russell Bryant
4612b4ccca issue #5815
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7167 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-21 13:17:32 +00:00
Russell Bryant
3245bf61a1 issue #5775
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7165 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-21 02:44:06 +00:00
Russell Bryant
9ee13167bb issue #5787
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7163 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-21 02:03:23 +00:00
Russell Bryant
ca9633ca9b issue #5794
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7157 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-21 01:00:51 +00:00
Russell Bryant
e04884545c issue #5806
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7155 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-21 00:03:40 +00:00
Russell Bryant
aa2239a050 issue #5773
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7154 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-20 23:56:49 +00:00
Russell Bryant
40a1b60cbd issue #5774
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7153 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-20 23:51:58 +00:00
Russell Bryant
cccb11916f fix logic for n+101 jumps
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7152 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-20 23:42:43 +00:00
Russell Bryant
49641825eb issue #5795
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7151 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-20 23:36:45 +00:00
Russell Bryant
c14c078405 issue #5792
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7150 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-20 23:33:03 +00:00
Russell Bryant
f2af073588 issue #5799
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7149 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-20 23:27:28 +00:00
Russell Bryant
b9a5eddb6d fix issue number for previous commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7148 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-20 23:22:10 +00:00
Russell Bryant
bffc815375 issue #5791
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7147 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-20 23:21:40 +00:00
Russell Bryant
5c3f322364 Shorten the module description (issue #5791)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7146 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-20 23:18:01 +00:00
Russell Bryant
3a6fae817c fix the output of Makefile generated variables to doxygen
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7133 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-18 04:13:39 +00:00
Russell Bryant
d8f74ecb94 Add missing carriage return and line feed to the SDP line indicating that we don't support VAD (issue #5780)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7131 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-17 20:26:27 +00:00
Kevin P. Fleming
f7f2b1b033 fix remaining breakage related to chan_modem modules
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7127 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-17 04:26:07 +00:00
Admin Commit
601ab7ff82 This commit was manufactured by cvs2svn to create branch 'v1-2'.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7126 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-16 22:40:43 +00:00
1311 changed files with 112631 additions and 268808 deletions

View File

@@ -1 +1 @@
33
8

View File

@@ -1 +1 @@
33
8

View File

@@ -1 +1 @@
1.4.24.1
1.2.7

4
BUGS
View File

@@ -7,10 +7,10 @@ the official Asterisk Bug Tracker at:
http://bugs.digium.com
For more information on using the bug tracker, or to
learn how you can contribute by acting as a bug marshal
learn how you can contribute by acting as a bug marshall
please see:
http://www.asterisk.org/developers/bug-guidelines
http://www.digium.com/index.php?menu=bugguidelines
If you would like to submit a feature request, please
resist the temptation to post it to the bug tracker.

499
CHANGES
View File

@@ -1,374 +1,127 @@
Changes since Asterisk 1.2:
Changes since Asterisk 1.2.0-beta2:
* over 4,000 commits since 1.2
* queue member naming
* CLI commands rework
o Change the way CLI commands are structured.
o Most commands are now <module> <verb> <args>
* chan_h323 update
* RTP packetization
* SLA (Shared Line Appearance) support
* T.38 Passthrough Support for faxing in SIP
* Generic channel jitterbuffer (spawned from RTP)
* Variable Length DTMF for better DTMF compatibility
* Improved chan_iax2 scalability by using multithreading
* AEL2 has replaced the original implementation of AEL. The "2" is removed. For more details,
read: http://www.voip-info.org/wiki/view/Asterisk+AEL2
AEL is no longer considered experimental.
* New sounds; English, Spanish, and French prompts, as well as music on hold files, in
multiple Asterisk native formats.
* IMAP storage of voicemail
* Jabber/GoogleTalk integration
* New speech recognition API for interfacing to different Voice Recognition software packages
* much more customizable and portable build system
o also for asterisk-addons
* Radius CDR logging
* SNMP support
* SMDI (Simplified Message Desk Interface) support
* Redesign of MusicOnHold configuration settings
* Manager over HTTP
* Significant chan_skinny updates
* Significant chan_misdn updates
* Improved SIP transfers
* SIP MWI subscription support
* Much improved support for SIP video
* Control over SIP transfers and subscriptions (enable/disable per device)
* ChanSpy whisper mode (Whisper Paging)
* Configurable language support for saying dates and times
* Significant architecture improvements for memory usage and performance
* Media-only IAX2 transfers
* Updates to the Radio Repeater app code
* Deprecation of AgentCallbackLogin in favor of a dialplan-based solution
* uClibc builds supported
* Work done for freeBSD portability
* Work done for Solaris portability
* FreeTDS-based database can be used with Realtime
* New internal data structure, stringfields, is implemented in IAX and SIP, reducing memory consumption by about 50%.
* Use of thread local storage for reduced memory allocation/freeing and lower stack consumption
* Reorganized files into docs/ main/ configs/, including name changes in some cases
* Much effort was expended in arranging documentation in source files in doxygen format
* Improved IP TOS support for IAX and SIP
* Builtin mini HTTP server
* Added support for Sigma Designs cards.
* Frame header caching to reduce memory allocation/freeing
* Passthrough and record/playback support for G.722 wideband audio
* using mpg123 to play MP3 files for music-on-hold will be deprecated in 1.4 (start using the "native support")
* New Apps:
1. AMD() ;; Answering Machine Detection
2. ChannelRedirect() ;; asynch goto, redirect chan to context/exten/priority
3. ContinueWhile() ;; Addition to the While() suite. Acts like "continue".
4. ExitWhile() ;; Addition to the While() suite. Acts like "break".
5. ExtenSpy() ;; A close cousin to ChanSpy().
6. FollowMe() ;; findme/followme call redirect app
7. Log() ;; Send a message to the log, based on severity level.
8. MacroExclusive() ;; No more than one invocation of this macro allowed at any one time.
9. MorseCode() ;; turns strings into dits and dahs. A playground for ham radio licensees!
10. OSPAuth() ;; OSP authentication
11. QueueLog() ;; allows you to write your own events into the queue log
12. SLAStation() ;; Shared Line Appearance
13. SLATrunk() ;; Shared Line Appearance
14. SpeechCreate() ;; Voice Recognition Engine interface...
15. SpeechActivateGrammar()
16. SpeechStart()
17. SpeechBackground
18. SpeechDeactivateGrammar()
19. SpeechProcessingSound()
20. SpeechDestroy()
21. SpeechLoadGrammar()
22. SpeechUnloadGrammar()
23. StopMixMonitor() ;; to stop the MixMonitor App.
24. TryExec() ;; execute dialplan app without fatal consequences
* Apps removed:
1. CheckGroup -- do a comparison to ${GROUP()}
2. Curl -- use the function CURL() instead
3. Cut -- use the function CUT() instead
4. DateTime -- use sayunixtime() app instead.
5. DBget -- deprecated in 1.2, now removed.
6. DBput -- deprecated in 1.2, now removed.
7. Enumlookup -- use the function ENUMLOOKUP() instead
8. Eval -- use the function EVAL() instead
9. GetGroupCount -- use the function GROUP_COUNT() instead
10. GetGroupMatchCount -- use the function GROUP_MATCH_COUNT() instead
11. Intercom -- use the chan_oss module instead
12. Math -- use the function MATH() instead
13. MD5 -- use the function MD5() instead
14. SetCIDname -- use the function CALLERID(name) instead
15. SetCIDnum -- use the function CALLERID(number) instead
16. SetGroup -- use Set(GROUP=group) instead
17. SetRDNIS -- use the function CALLERID(rdnis) instead
18. Sql_postgres -- was deprecated in 1.2, now removed
19. Txtcidname -- use the function TXTCIDNAME instead
* New Dialplan Functions:
1. ARRAY()
2. BASE_64_DECODE()
3. BASE_64_ENCODE()
4. CHANNEL()
5. CURL()
6. CUT()
7. DB_DELETE()
8. FILTER()
9. GLOBAL()
10. IFTIME()
11. KEYPADHASH()
12. ODBC()
13. QUOTE()
14. RAND()
15. REALTIME()
16. SHA1()
17. SORT()
18. SPRINTF()
19. SQL_ESC()
20. STAT()
21. STRPTIME()
22. AUDIOHOOK_INHERIT()
* Apps that have changes to their interface:
1. Authenticate() -- optional maxdigits argument added.
2. ChanSpy() -- new options:
o w -- Enable 'whisper' mode, so the spying channel can talk to...
o W -- Enable 'private whisper' mode, so the spying channel can...
3. DBdel() -- now marked as DEPRECATED in favor of the DB_DELETE func
4. Dial()
o New Option: O([x]) for Zaptel operator mode
o New Option: K/k parking via dtmf tones
5. Dictate() -- optional filename argument added.
6. Directory() -- new option: e - In addition to the name, also read the extension number...
7. ForkCDR() -- new options:
o 'a' -- update answer time on new cdr
o 'A' -- Lock the orig CDR answer time against changes.
o 'D' -- Copy the disposition from the orig to the new CDR.
o 'd' -- clear the dstcannel field in the new CDR.
o 'e' -- set the end time of the original CDR.
o 'R' -- do NOT reset the new CDR.
o 's' -- Add/change var in orig CDR.
o 'T' -- Force ast_cdr_end, answer to obey LOCKED flag for the orig. CDR.
-- ast_cdr_setvar will be forced also (used by the CDR() func in write mode)
8. Meetme() -- new options:
o 'I' -- announce user join/leave without review
o 'l' -- set listen only mode (Listen only, no talking)
o 'o' -- set talker optimization - treats talkers who aren't speaking as...
o '1' -- do not play message when first person enters
9. MeetmeAdmin() -- new options:
o 'r' -- Reset one user's volume settings
o 'R' -- Reset all users volume settings
o 's' -- Lower entire conference speaking volume
o 'S' -- Raise entire conference speaking volume
o 't' -- Lower one user's talk volume
o 'T' -- Lower all users talk volume
o 'u' -- Lower one user's listen volume
o 'U' -- Lower all users listen volume
o 'v' -- Lower entire conference listening volume
o 'V' -- Raise entire conference listening volume
10. OSPFinish() : now also can return ERROR result.
11. OSPLookup() : Sets more variables, also now returns ERROR result.
12. Page() -- New option: r - record the page into a file (see 'r' for app_meetme)
13. Pickup() -- multiple extensions, PICKUPMARK; read the description!
14. Queue()
o New Argument: AGI
o New option: i
15. Random() -- is now deprecated in 1.4
16. Read() -- replace 'skip' and 'noanswer' options with 's', 'n', add 'i' option.
17. Record() -- New option: 'x' : ignore all terminator keys (DTMF) and keep recording until hangup
18. UserEvent() -- slight change in behavior. Read the description.
19. VoiceMailMain() -- new a(#) option, goes to folder # directly.
20. WaitForSilence() -- new optional 3rd arg, time delay before returning.
* Functions that have changes to their interfaces:
1. CDR -- new options: u and s
2. LANGUAGE -- Deprecated. Use CHANNEL(language) instead.
3. MUSICCLASS -- Deprecated. Use CHANNEL(musicclass) instead.
* Configuration File Changes:
1. NEW config files:
1. amd.conf -- Answering Machine Detection parameters
2. followme.conf -- parameters for the findme/followme call forwarding
3. func_odbc.conf -- define sql access functions here
4. gtalk.conf -- how to handle gtalk protocol calls
5. h323.conf -- h323 configuration
6. http.conf -- config for the builtin mini-http server in asterisk
7. jabber.conf -- jabber interface
8. jingle.conf -- jingle protocol interface config
10. res_snmp.conf -- to enable snmp in asterisk, and define full/sub agent status
11. say.conf -- define per-language rules for numbers, dates, etc.
12. skinny.conf -- for those special skinny phones you want to use...
13. sla.conf -- Shared Line Appearance config
14. smdi.conf -- SMDI messaging config
15. udptl.conf -- T38's udptl transport config
16. users.conf -- user config
2. Changes to Existing Config files:
1. In General:
o Jitterbuffer support added to several channels. Usually adds these variables to a config file:
1. jbenable
2. jbmaxsize
3. jbresyncthreshold
4. jbimpl
5. jblog
o MusicOnHold upgrade introduces two new variables:
1. mohinterpret
2. mohsuggest
2. agents.conf
o multiplelogin variable added
o maxlogintries variable added
o autologoffunavail variable added
o endcall variable added
o goodbye variable added
o createlink variable REMOVED
3. alsa.conf
o mohinterpret variable added
o Jitterbuffer variables added
4. cdr.conf
o endbeforehexten variable added
o sections for csv and radius added, with variables usegmtime, loguniqueid,
loguserfield, and radiuscfg variables.
5. cdr_tds.conf
o table variable added
6. extensions.ael
o Many upgrades. See the info at http://www.voip-info.org/wiki/view/Asterisk+AEL2
7. extensions.conf
o autofallthru now set to "yes" by default
o userscontext variable added
o added info/examples on paging and hints.
8. features.conf
o parkedplay variable added (who to beep at)
o parkedmusicclass
o atxfernoanswertimeout variable added
o parkcall variable added (one step parking)
o improved documentation for dynamic feature declarations!
o added parkedcallltransfers option to control builtin transfers with parking
o added parkedcallparking option to control one touch parking w/ parking pickup
o added parkedcallhangup option to control disconnect feature w/ parking pickup
o added parkedcallrecording option to control one-touch record w/ parking pickup
o added BRIDGE_FEATURES variable to set available features for a channel
9. iax.conf
o adsi variable added
o mohinterpret variable added
o mohsuggest variable added
o jitterbuffer updates
o iaxthreadcount variable added
o iaxmaxthreadcount variable added
o the way to specify TOS has changed.
o mailboxdetail variable has been REMOVED.
10. indications.conf
o [bg] entry added (Bulgaria).
o [il] entry added (Israel)
o [in] entry added (India)
o [jp] entry added (Japan)
o [my] entry added (Malaysia)
o [th] entry added (Thailand)
11. manager.conf
o webenabled variable added
o httptimeout variable added
o timestampevents variable added
12. mgcp.conf
o Jitterbuffer support added
13. misdn.conf
o l1watcher_timeout variable added
o pp_l2_check variable added
o echocancelwhenbridged variable added
o echotraining variable added
o max_incoming variable added
o max_outgoing variable added
14. modules.conf
o a comment for preloading res_speech.so is added
o mention of global symbols is removed
o obsolesced entries for chan_modem_* and app_intercom have been removed
15. musiconhold.conf
o the default is now to do native moh from /var/lib/asterisk/moh
16. osp.conf
o authpolicy variable added
17. oss.conf
o debug variable added
o device variable added
o mixer variable added
o boost variable added
o callerid variable added
o autohangup variable added
o queuesize variable added
o frags variable added
o JitterBuffer support
o sections to define alternate sound cards
18. queues.conf
o autofill variable added
o monitor-type variable added
o musiconhold is now musicclass, with a difference in interpretation
o autofill variable added
o autopause variable added
o setinterfacevar variable added
o ringinuse variable added
19. res_odbc.conf
o pooling variable added
20. rpt.conf
o duplex variable added
o tailmessagetime variable added
o tailsquashedtime variable added
o tailmessages variable added
21. rtp.conf
o rtcpinterval varaible added
22. sip.conf
o allowguest variable can't be set to 'osp'
o allowoverlap variable added
o allowtransfer variable added
o limitonpeer variable added
o directrtpsetup variable added
o buggymwi variable added
o ospauth variable REMOVED
o notifyhold variable added
o autoframing variable added
o tos variable REMOVED
o tos_sip variable added
o tos_audio variable added
o tos_video variable added
o minexpiry variable added
o t1min variable added
o musicclass variable REMOVED
o mohinterpret variable added
o mohsuggest variable added
o allowsubscribe variable added
o videosupport variable added
o maxcallbitrate variable added
o g726nonstandard variable added
o dumphistory variable added
o t38pt_udptl variable added
o t38pt_rtp variable added
o t38pt_tcp variable added
o rfc2833compensate variable added
o matchexterniplocally variable added
o canreinvite variable can also now be set to 'nonat'
o rtsavesysname variable added
o JitterBuffer support added
o t38pt_usertpsource variable added
o regcontext variable can contains multiple contexts separated by an '&'
23. skinny.conf
o port variable renamed to bindport
o JitterBuffer support added
o model variable REMOVED
o mohinterpret variable added
o mohsuggest variable added
o speeddial variable added
o addon variable added
24. voicemail.conf
o userscontext variable added
o smdiport variable added
o attachfmt variable added
o volgain variable added
o tempgreetwarn variable added
25. zapata.conf
o pritimer variable has improved documentation
o New signalling method: fgccama
o New signalling method: fgccamamf
o outsignalling variable added
o distinctiveringaftercid variable added
o cidsignalling now also accepts v23_jp, and smdi
o usesmdi variable added
o smdiport variable added
o mohinterpret variable added
o mohsuggest variable added
o JitterBuffer support added
* Removed Codecs/Channels:
1. codec_g723 was removed because the actual codec implementation it was designed to use is not distributable
2. chan_modem_* and related modules are gone because the kernel support for those interfaces is old, buggy and unsupported
* New Utils:
1. aelparse -- compile .ael files outside of asterisk
* New manager events:
1. OriginateResponse event comes to replace OriginateSuccess and OriginateFailure
* iLBC source code no longer included (see UPGRADE.txt for details)
* New CLI command "pri show version" that shows the current version of libpri
that the library was built against (requires a version of libpri since this API
feature was added).
* Cygwin build system portability
* Optional generation of outbound silence during channel recording
Changes since Asterisk 1.2.0-beta1:
* Many, many bug fixes
* Documentation and sample configuration updates
* Vastly improved presence/subscription support in the SIP channel driver
* A new (experimental) mISDN channel driver
* A new monitoring application (MixMonitor)
* More portability fixes for non-Linux platforms
* New dialplan functions replacing old applications
* Significant deadlock and performance upgrades for the Manager interface
* An upgrade to the 'new' dialplan expression parser for all users
* New Zaptel echo cancellers with improved performance
* Support for the latest OSP toolkit from TransNexus
* Support user-controlled volume adjustment in MeetMe application
* More dialplan applications now return status variables instead of priority jumping
* Much more powerful ENUM support in the dialplan
* SIP domain support for authentication and virtual hosting
* Many PRI protocol updates and fixes, including more complete Q.SIG support
* New applications: Pickup() and Page()
Changes since Asterisk 1.0:
This list currently only containts changes made from the end of November until
March 26, 2005.
* Add new applications:
-- AgentMonitorOutgoing
-- Curl
-- ExecIf
-- ExecIfTime
-- IAX2Provision
-- MacroExit
-- MacroIf
-- PauseQueueMember
-- ReadFile
-- SetRDNIS
-- SIPAddHeader
-- SIPGetHeader
-- StartMusicOnHold
-- StopMusicOnHold
-- UnpauseQueueMember
-- WaitForSilence
-- While / EndWhile
* app Answer
-- added delay option
* app ChanIsAvail
-- added 's' option
* app Dial
-- add option to specify the class for musiconhold with m option
* app EnumLookup
-- added "reload enum" for configuration
* app Goto
-- added relative priorities
* app GotoIf
-- added relative priorities
* app MeetMe
-- added 'i' option
-- added 'r' option
-- added 'T' option
-- added 'P' option
-- added 'c' option
-- added adminpin to meetme.conf
-- added reload command
* app PrivacyManager
-- add config file privacy.conf
* app queue
-- queues.conf
-- added persistentmembers option to queues.conf
-- changed music option to musiconhold
-- added weight option
-- added note about why agent groups probably shouldn't be used
-- added timeoutrestart option
* app Read
-- added attempts parameter
-- added timeout parameter
* app Record
-- added 'q' option
* app SendDTMF
-- add timeout option
* app SMS
-- document alternative syntax for queueing messages
* app Voicemail
-- add info about VM_CATEGORY
-- voicemail.conf
-- added usedirectory option
-- added VM_CIDNUM and VM_CIDNAME in message config
* chan IAX2
-- new jitterbuffer
-- added setvar option
-- added regex to iax2 show peers/users
-- allow multiple bindaddr lines in iax.conf
-- added reload command
-- added forcejitterbuffer option
-- added note about specifying bindport before bindaddr
-- added trunktimestamps option
* chan Agent
-- added agent logoff CLI command
* chan OSS
-- added Flash CLI command
* chan SIP
-- added setvar option
-- added compactheaders option
-- added usereqphone option
-- added registertimeout option
-- added externhost option
-- added sip notify CLI command
-- added sip_notify.conf
-- added allowguest option
* chan Zap
-- added hanguponplarityswitch option
-- added sendcalleridafter option
-- added priresetinterval option
-- added TON/NPI config options (the ones right above the resetinterval option)
-- added answeronpolarityswitch option
-- added "never" for resetinterval
* extensions
-- allow '*' when including files (#include "sip-*.conf")
-- added eswitch
* General
-- added #exec syntax for including output from a command
-- added show features CLI command
-- added configuration templates for category inheritance

88
CREDITS
View File

@@ -27,149 +27,69 @@ Wasim - Hangup detect
* Thanks to QuickNet Technologies for their donation of an Internet
PhoneJack and Linejack card to the project. (http://www.quicknet.net)
* Thanks to VoipSupply for their donation of Sipura ATAs to the project for
T.38 testing. (http://www.voipsupply.com)
* Thanks to Grandstream for their donation of ATAs to the project for
T.38 testing. (http://www.grandstream.com)
=== MISCELLANEOUS PATCHES ===
Jim Dixon - Zapata Telephony and app_rpt
http://www.zapatatelephony.org/app_rpt.html
Russell Bryant - Asterisk 1.0 maintainer and misc. enhancements
russelb@clemson.edu
Anthony Minessale II - Countless big and small fixes, and relentless forward push
ChanSpy, ForkCDR, ControlPlayback, While/EndWhile, DumpChan, Dictate,
MacroIf, ExecIf, ExecIfTime, RetryDial, MixMonitor applications; many realtime
concepts and implementation pieces, including res_config_odbc; format_slin;
cdr_custom; several features in Dial including L(), G() and enhancements to
M() and D(); several CDR enhancements including CDR variables; attended
transfer; one touch record; native MOH; manager eventmask; command line '-t'
flag to allow recording/voicemail on nfs shares; #exec command and multiline
comments in config files; setvar in iax and sip configs.
anthmct@yahoo.com http://www.asterlink.com
James Golovich - Innumerable contributions
You can find him and asterisk-perl at http://asterisk.gnuinter.net
Andre Bierwirth - Extension hints and status
Oliver Daudey - ISDN4Linux fixes
Pauline Middelink - ISDN4Linux patches and some general patches.
She can be found at http://www.polyware.nl/~middelink/En/
Jean-Denis Girard - Various contributions from the South Pacific Islands
jd-girard@esoft.pf http://www.esoft.pf
William Jordan / Vonage - MySQL enhancements to Voicemail
wjordan@vonage.com
Jac Kersing - Various fixes
Steven Critchfield - Seek and Trunc functions for playback and recording
critch@basesys.com
Jefferson Noxon - app_lookupcidname, app_db, and various other contributions
Klaus-Peter Junghanns - in-band DTMF on SIP and MGCP
Ross Finlayson - Dynamic RTP payload support
Mahmut Fettahlioglu - Audio recording, music-on-hold changes, alaw file
format, and various fixes. Can be contacted at mahmut@oa.com.au
James Dennis - Cisco SIP compatibility patches to work with SIP service
providers. Can be contacted at asterisk@jdennis.net
Tilghman Lesher - ast_localtime(); ast_say_date_with_format();
GotoIfTime, Random, SayUnixTime, HasNewVoicemail applications;
CUT, SORT, EVAL, CURL, FIELDQTY, STRFTIME, QUEUEAGENT* functions;
and other innumerable bug fixes. http://asterisk.drunkcoder.com/
Jayson Vantuyl - Manager protocol changes, various other bugs.
jvantuyl@computingedge.net
Thorsten Lockert - OpenBSD, FreeBSD ports, making MacOS X port run on 10.3,
dialplan include verification, route lookup on OpenBSD, SNMP agent
support (res_snmp), various other bugs. tholo@sigmasoft.com
dialplan include verification, route lookup on OpenBSD, various other
bugs. tholo@sigmasoft.com
Brian West - ODBC support and Bug Marshaling
Josh Roberson - chan_zap reload support, Advanced Voicemail Features, other misc. patches,
and Bug Marshalling. - josh@asteriasgi.com, http://www.asteriasgi.com
William Waites - syslog support, SIP NAT traversal for SIP-UA. ww@styx.org
Rich Murphey - Porting to FreeBSD, NetBSD, OpenBSD, and Darwin.
rich@whiteoaklabs.com http://whiteoaklabs.com
Simon Lockhart - Porting to Solaris (based on work of Logan ???)
simon@slimey.org
Olle E. Johansson - SIP RFC compliance, documentation and testing, testing, testing
oej@edvina.net, http://edvina.net
Steve Kann - new jitter buffer for IAX2
stevek@stevek.com
Constantine Filin - major contributions to the Asterisk Realtime Architecture
Steve Murphy - privacy support, $[ ] parser upgrade, AEL2 parser upgrade
Steve Murphy - privacy support
Claude Patry - bug fixes, feature enhancements, and bug marshalling
cpatry@gmail.com
Miroslav Nachev, miro@space-comm.com COSMOS Software Enterprises, Ltd.
- for Variable for No Answer Timeout for Attended Transfer
Slav Klenov & Vanheuverzwijn Joachim - development of the generic jitterbuffer
Securax Ltd. info@securax.be
Roy Sigurd Karlsbakk - providing funding for generic jitterbuffer development
roy@karlsbakk.net, Briiz Telecom AS
Voop A/S, Nuvio Inc, Inotel S.A and Foniris Telecom A/S - funding for rewrite of SIP transfers
Philippe Sultan - RADIUS CDR module
INRIA, http://www.inria.fr/
John Martin, Aupix - Improved video support in the SIP channel
Steve Underwood - Provided T.38 pass through support.
George Konstantoulakis - Support for Greek in voicemail added by InAccess Networks (work funded by HOL, www.hol.gr) gkon@inaccessnetworks.com
Daniel Nylander - Support for Swedish and Norwegian languages in voicemail. http://www.danielnylander.se/
Stojan Sljivic - An option for maximum number of messsages per mailbox in voicemail. Also an issue with voicemail synchronization has been fixed. GDS Partners www.gdspartners.com . stojan.sljivic@gdspartners.com
Bartosz Supczinski - Support for Polish added by DIR (www.dir.pl) Bartosz.Supczinski@dir.pl
James Rothenberger - Support for IMAP storage integration added by OneBizTone LLC Work funded by University of Pennsylvania jar@onebiztone.com
Paul Cadach - Bringing chan_h323 up to date, bug fixes, and more!
=== OTHER CONTRIBUTIONS ===
John Todd - Monkey sounds and associated teletorture prompt
Michael Jerris - bug marshaling
Leif Madsen, Jared Smith and Jim van Meggelen - the Asterisk book
available under a Creative Commons License at http://www.asteriskdocs.org
Brian M. Clapper - poll.c emulation
This product includes software developed by Brian M. Clapper <bmc@clapper.org>
=== HOLD MUSIC ===
Music provided by www.freeplaymusic.com
Music provided by www.opsound.org
=== OTHER SOURCE CODE IN ASTERISK ===
Asterisk uses libedit, the lightweight readline replacement from NetBSD.
The cdr_radius module uses libradiusclient-ng, which is also from NetBSD.
They are BSD-licensed and require the following statement:
This product includes software developed by the NetBSD
Foundation, Inc. and its contributors.
Digium did not implement the codecs in Asterisk. Here is the copyright on the
GSM source:

23629
ChangeLog

File diff suppressed because it is too large Load Diff

View File

@@ -2,16 +2,19 @@ A PBX is only really useful if you can get calls into it. Of course, you
can use Asterisk with VoIP calls (SIP, H.323, IAX), but you can also talk
to the real PSTN through various cards.
Supported Hardware is divided into two general groups: DAHDI devices and
non-DAHDI devices. The DAHDI compatible hardware supports pseudo-TDM
conferencing and all call features through chan_dahdi, whereas non-DAHDI
Supported Hardware is divided into two general groups: Zaptel devices and
non-zaptel devices. The Zaptel compatible hardware supports pseudo-TDM
conferencing and all call features through chan_zap, whereas non-zaptel
compatible hardware may have different features.
DAHDI compatible hardware
Zaptel compatible hardware
==========================
-- Digium (Primary author of Asterisk)
http://www.digium.com, http://store.digium.com
http://www.digium.com, http://store.yahoo.com/asteriskpbx
* Wildcard X100P - Single FXO interface connects to Loopstart phone
line
* Wildcard T400P (obsolete) - Quad T1 interface connects to four T1/PRI
interfaces. Supports RBS and PRI voice and PPP, FR, and HDLC data.
@@ -25,13 +28,16 @@ DAHDI compatible hardware
* Wildcard E100P - Single E1 interface connects to a single E1/PRI (or PRA)
interface. Supports PRA/PRI, EuroISDN voice and PPP, FR, HDLC data.
* Wildcard S100U - Single FXS interface connects to a standard analog
telephone.
* Wildcard TDM400P - Quad Modular FXS interface connects to standard
analog telephones.
* Wildcard TE410P - Quad T1/E1 switchable interface. Supports PRI and
RBS signalling, as well as PPP, FR, and HDLC data modes.
Non-DAHDI compatible hardware
Non-zaptel compatible hardware
==============================
-- QuickNet, Inc.
@@ -43,26 +49,16 @@ Non-DAHDI compatible hardware
* Internet LineJack - Single FXS or FXO interface. Supports Linux
telephony interface.
mISDN compatible hardware
=========================
mISDN homepage: http://www.isdn4linux.de/mISDN/
Any adapter with an mISDN driver should be compatible with
chan_misdn. See misdn.txt for information.
-- beroNet
http://www.beronet.com
* BN4S0 - 4 Port BRI card (TE/NT)
* BN8S0 - 8 Port BRI card (TE/NT)
* Billion Card - Single Port BRI card (TE (/NT with crossed cable) )
Miscellaneous other interfaces
==============================
-- ISDN4Linux
http://www.isdn4linux.de/
* Any ISDN terminal adapter supported by isdn4linux should provide
connectivity.
-- ALSA
http://www.alsa-project.org

26
LICENSE
View File

@@ -5,18 +5,6 @@ applies to all loadable Asterisk modules used on your system as well,
except as defined below. The GPL (version 2) is included in this
source tree in the file COPYING.
This package also includes various components that are not part of
Asterisk itself; these components are in the 'contrib' directory
and its subdirectories. Most of these components are also
distributed under the GPL version 2 as well, except for the following:
contrib/firmware/iax/iaxy.bin:
This file is Copyright (C) Digium, Inc. and is licensed for
use with Digium IAXy hardware devices only. It can be
distributed freely as long as the distribution is in the
original form present in this package (not reformatted or
modified).
Digium, Inc. (formerly Linux Support Services) holds copyright
and/or sufficient licenses to all components of the Asterisk
package, and therefore can grant, at its sole discretion, the ability
@@ -31,8 +19,8 @@ there is no requirement that you provide the same exception in your
GPL'd products (although if you've written a module for Asterisk we
would strongly encourage you to make the same exception that we do).
Specific permission is also granted to link Asterisk with OpenSSL, OpenH323
and/or the UW IMAP Toolkit and distribute the resulting binary files.
Specific permission is also granted to link Asterisk with OpenSSL and
OpenH323.
In addition, Asterisk implements two management/control protocols: the
Asterisk Manager Interface (AMI) and the Asterisk Gateway Interface
@@ -50,19 +38,19 @@ and use of them is subject to our trademark licensing policies. If you
wish to use these trademarks for purposes other than simple
redistribution of Asterisk source code obtained from Digium, you
should contact our licensing department to determine the necessary
steps you must take. For more information on this policy, please read
http://www.digium.com/en/company/profile/trademarkpolicy.php
steps you must take.
If you have any questions regarding our licensing policy, please
contact us:
+1.877.344.4861 (via telephone in the USA)
+1.877.546.8963 (via telephone in the USA)
+1.256.428.6000 (via telephone outside the USA)
+1.256.864.0464 (via FAX inside or outside the USA)
IAX2/pbx.digium.com (via IAX2)
IAX2/misery.digium.com/6000 (via IAX2)
licensing@digium.com (via email)
Digium, Inc.
445 Jan Davis Drive
150 West Park Loop
Suite 100
Huntsville, AL 35806
USA

1084
Makefile

File diff suppressed because it is too large Load Diff

View File

@@ -1,112 +0,0 @@
#
# Asterisk -- A telephony toolkit for Linux.
#
# Makefile rules for subdirectories containing modules
#
# Copyright (C) 2006, Digium, Inc.
#
# Kevin P. Fleming <kpfleming@digium.com>
#
# This program is free software, distributed under the terms of
# the GNU General Public License
#
ifeq ($(findstring LOADABLE_MODULES,$(MENUSELECT_CFLAGS)),)
ASTCFLAGS+=${GC_CFLAGS}
endif
ifneq ($(findstring STATIC_BUILD,$(MENUSELECT_CFLAGS)),)
STATIC_BUILD=-static
endif
include $(ASTTOPDIR)/Makefile.rules
comma:=,
$(addsuffix .o,$(C_MODS)): ASTCFLAGS+=-DAST_MODULE=\"$*\" $(MENUSELECT_OPTS_$*:%=-D%) $(foreach dep,$(MENUSELECT_DEPENDS_$*),$(value $(dep)_INCLUDE))
$(addsuffix .oo,$(CC_MODS)): ASTCFLAGS+=-DAST_MODULE=\"$*\" $(MENUSELECT_OPTS_$*:%=-D%) $(foreach dep,$(MENUSELECT_DEPENDS_$*),$(value $(dep)_INCLUDE))
$(LOADABLE_MODS:%=%.so): ASTCFLAGS+=-fPIC
$(LOADABLE_MODS:%=%.so): LIBS+=$(foreach dep,$(MENUSELECT_DEPENDS_$*),$(value $(dep)_LIB))
$(LOADABLE_MODS:%=%.so): ASTLDFLAGS+=$(foreach dep,$(MENUSELECT_DEPENDS_$*),$(value $(dep)_LDFLAGS))
$(addsuffix .so,$(filter $(LOADABLE_MODS),$(C_MODS))): %.so: %.o
$(addsuffix .so,$(filter $(LOADABLE_MODS),$(CC_MODS))): %.so: %.oo
modules.link: $(addsuffix .o,$(filter $(EMBEDDED_MODS),$(C_MODS)))
modules.link: $(addsuffix .oo,$(filter $(EMBEDDED_MODS),$(CC_MODS)))
.PHONY: clean uninstall _all moduleinfo makeopts
ifneq ($(LOADABLE_MODS),)
_all: $(LOADABLE_MODS:%=%.so)
endif
ifneq ($(EMBEDDED_MODS),)
_all: modules.link
__embed_ldscript:
@echo "../$(SUBDIR)/modules.link"
__embed_ldflags:
@echo "$(foreach mod,$(filter $(EMBEDDED_MODS),$(C_MODS)),$(foreach dep,$(MENUSELECT_DEPENDS_$(mod)),$(dep)_LDFLAGS))"
@echo "$(foreach mod,$(filter $(EMBEDDED_MODS),$(CC_MODS)),$(foreach dep,$(MENUSELECT_DEPENDS_$(mod)),$(dep)_LDFLAGS))"
__embed_libs:
@echo "$(foreach mod,$(filter $(EMBEDDED_MODS),$(C_MODS)),$(foreach dep,$(MENUSELECT_DEPENDS_$(mod)),$(dep)_LIB))"
@echo "$(foreach mod,$(filter $(EMBEDDED_MODS),$(CC_MODS)),$(foreach dep,$(MENUSELECT_DEPENDS_$(mod)),$(dep)_LIB))"
else
__embed_ldscript:
__embed_ldflags:
__embed_libs:
endif
modules.link:
@rm -f $@
@for file in $(patsubst %,$(SUBDIR)/%,$(filter %.o,$^)); do echo "INPUT (../$${file})" >> $@; done
@for file in $(patsubst %,$(SUBDIR)/%,$(filter-out %.o,$^)); do echo "INPUT (../$${file})" >> $@; done
clean::
rm -f *.so *.o *.oo *.s *.i *.ii
rm -f .*.d
rm -f modules.link
install:: all
for x in $(LOADABLE_MODS:%=%.so); do $(INSTALL) -m 755 $$x $(DESTDIR)$(MODULES_DIR) ; done
uninstall::
dist-clean::
rm -f .*.moduleinfo .moduleinfo
rm -f .*.makeopts .makeopts
.%.moduleinfo: %.c
@echo "<member name=\"$*\" displayname=\"$(shell $(GREP) -e AST_MODULE_INFO $< | head -n 1 | cut -d '"' -f 2)\" remove_on_change=\"$(SUBDIR)/$*.o $(SUBDIR)/$*.so\">" > $@
$(AWK) -f $(ASTTOPDIR)/build_tools/get_moduleinfo $< >> $@
echo "</member>" >> $@
.%.moduleinfo: %.cc
@echo "<member name=\"$*\" displayname=\"$(shell $(GREP) -e AST_MODULE_INFO $< | head -n 1 | cut -d '"' -f 2)\" remove_on_change=\"$(SUBDIR)/$*.oo $(SUBDIR)/$*.so\">" > $@
$(AWK) -f $(ASTTOPDIR)/build_tools/get_moduleinfo $< >> $@
echo "</member>" >> $@
.moduleinfo:: $(addsuffix .moduleinfo,$(addprefix .,$(ALL_C_MODS) $(ALL_CC_MODS)))
@echo "<category name=\"MENUSELECT_$(MENUSELECT_CATEGORY)\" displayname=\"$(MENUSELECT_DESCRIPTION)\" remove_on_change=\"$(SUBDIR)/modules.link\">" > $@
@cat $^ >> $@
@echo "</category>" >> $@
moduleinfo: .moduleinfo
@cat $<
.%.makeopts: %.c
@$(AWK) -f $(ASTTOPDIR)/build_tools/get_makeopts $< > $@
.%.makeopts: %.cc
@$(AWK) -f $(ASTTOPDIR)/build_tools/get_makeopts $< > $@
.makeopts:: $(addsuffix .makeopts,$(addprefix .,$(ALL_C_MODS) $(ALL_CC_MODS)))
@cat $^ > $@
makeopts: .makeopts
@cat $<
ifneq ($(wildcard .*.d),)
include .*.d
endif

View File

@@ -1,129 +0,0 @@
#
# Asterisk -- A telephony toolkit for Linux.
#
# Makefile rules
#
# Copyright (C) 2006-2008, Digium, Inc.
#
# Kevin P. Fleming <kpfleming@digium.com>
#
# This program is free software, distributed under the terms of
# the GNU General Public License
#
# Each command is preceded by a short comment on what to do.
# Prefixing one or the other with @\# or @ or nothing makes the desired
# behaviour. ECHO_PREFIX prefixes the comment, CMD_PREFIX prefixes the command.
-include $(ASTTOPDIR)/makeopts
.PHONY: dist-clean
# If 'make' decides to create intermediate files to satisfy a build requirement
# (like producing a .i from a .c), we want to keep them, so tell make to keep
# all intermediate files
.SECONDARY:
# extra cflags to build dependencies. Recursively expanded.
MAKE_DEPS=-MD -MT $@ -MF .$(subst /,_,$@).d -MP
ifeq ($(NOISY_BUILD),)
ECHO_PREFIX=@
CMD_PREFIX=@
else
ECHO_PREFIX=@\#
CMD_PREFIX=
endif
OPTIMIZE?=-O6
ifeq ($(findstring DONT_OPTIMIZE,$(MENUSELECT_CFLAGS)),)
# More GSM codec optimization
# Uncomment to enable MMXTM optimizations for x86 architecture CPU's
# which support MMX instructions. This should be newer pentiums,
# ppro's, etc, as well as the AMD K6 and K7.
#K6OPT=-DK6OPT
ASTCFLAGS+=$(OPTIMIZE)
endif
# shortcuts for common combinations of flags; these must be recursively expanded so that
# per-target settings will be applied
CC_CFLAGS=$(PTHREAD_CFLAGS) $(ASTCFLAGS)
CXX_CFLAGS=$(PTHREAD_CFLAGS) $(filter-out -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations $(AST_DECLARATION_AFTER_STATEMENT),$(ASTCFLAGS))
CC_LDFLAGS_SO=$(PTHREAD_CFLAGS) $(ASTLDFLAGS) $(SOLINK)
CXX_LDFLAGS_SO=$(PTHREAD_CFLAGS) $(ASTLDFLAGS) $(SOLINK)
CC_LIBS=$(PTHREAD_LIBS) $(LIBS)
CXX_LIBS=$(PTHREAD_LIBS) $(LIBS)
# determine whether to double-compile so that the optimizer can report code path problems
# this is only done when developer mode and DONT_OPTIMIZE are both enabled
# in that case, we run the preprocessor to produce a .i or .ii file from the source
# code, then compile once with optimizer enabled (and the output to /dev/null),
# and if that doesn't fail then compile again with optimizer disabled
ifeq ($(findstring DONT_OPTIMIZE,$(MENUSELECT_CFLAGS))$(AST_DEVMODE),DONT_OPTIMIZEyes)
COMPILE_DOUBLE=yes
endif
%.o: %.s
$(ECHO_PREFIX) echo " [AS] $< -> $@"
ifeq ($(COMPILE_DOUBLE),yes)
$(CMD_PREFIX) $(CC) -o /dev/null -c $< $(CC_CFLAGS) $(OPTIMIZE)
endif
$(CMD_PREFIX) $(CC) -o $@ -c $< $(CC_CFLAGS)
%.o: %.i
$(ECHO_PREFIX) echo " [CCi] $< -> $@"
ifeq ($(COMPILE_DOUBLE),yes)
$(CMD_PREFIX) $(CC) -o /dev/null -c $< $(CC_CFLAGS) $(OPTIMIZE)
endif
$(CMD_PREFIX) $(CC) -o $@ -c $< $(CC_CFLAGS)
ifneq ($(COMPILE_DOUBLE),yes)
%.o: %.c
$(ECHO_PREFIX) echo " [CC] $< -> $@"
$(CMD_PREFIX) $(CC) -o $@ -c $< $(CC_CFLAGS) $(MAKE_DEPS)
endif
%.i: %.c
$(ECHO_PREFIX) echo " [CPP] $< -> $@"
$(CMD_PREFIX) $(CC) -o $@ -E $< $(CC_CFLAGS) $(MAKE_DEPS)
%.oo: %.ii
$(ECHO_PREFIX) echo " [CXXi] $< -> $@"
ifeq ($(COMPILE_DOUBLE),yes)
$(CMD_PREFIX) $(CXX) -o /dev/null -c $< $(CXX_CFLAGS) $(OPTIMIZE)
endif
$(CMD_PREFIX) $(CXX) -o $@ -c $< $(CXX_CFLAGS)
ifneq ($(COMPILE_DOUBLE),yes)
%.oo: %.cc
$(ECHO_PREFIX) echo " [CXX] $< -> $@"
$(CMD_PREFIX) $(CXX) -o $@ -c $< $(CXX_CFLAGS) $(MAKE_DEPS)
endif
%.ii: %.cc
$(ECHO_PREFIX) echo " [CPP] $< -> $@"
$(CMD_PREFIX) $(CXX) -o $@ -E $< $(CXX_CFLAGS) $(MAKE_DEPS)
%.c: %.y
$(ECHO_PREFIX) echo " [BISON] $< -> $@"
$(CMD_PREFIX) bison -o $@ -d --name-prefix=ast_yy $<
%.c: %.fl
$(ECHO_PREFIX) echo " [FLEX] $< -> $@"
$(CMD_PREFIX) flex -o $@ --full $<
%.so: %.o
$(ECHO_PREFIX) echo " [LD] $^ -> $@"
$(CMD_PREFIX) $(CC) $(STATIC_BUILD) -o $@ $(CC_LDFLAGS_SO) $^ $(CC_LIBS)
%.so: %.oo
$(ECHO_PREFIX) echo " [LDXX] $^ -> $@"
$(CMD_PREFIX) $(CXX) $(STATIC_BUILD) -o $@ $(CXX_LDFLAGS_SO) $^ $(CXX_LIBS)
%: %.o
$(ECHO_PREFIX) echo " [LD] $^ -> $@"
$(CMD_PREFIX) $(CXX) $(STATIC_BUILD) -o $@ $(PTHREAD_CFLAGS) $(ASTLDFLAGS) $^ $(CXX_LIBS)
dist-clean:: clean

48
README
View File

@@ -1,17 +1,17 @@
The Asterisk(R) Open Source PBX
The Asterisk Open Source PBX
by Mark Spencer <markster@digium.com>
and the Asterisk.org developer community
Copyright (C) 2001-2009 Digium, Inc.
Copyright (C) 2001-2005 Digium, Inc.
and other copyright holders.
================================================================
* SECURITY
It is imperative that you read and fully understand the contents of
the security information file (doc/security.txt) before you attempt
to configure and run an Asterisk server.
the SECURITY file before you attempt to configure and run an Asterisk
server.
* WHAT IS ASTERISK?
* WHAT IS ASTERISK ?
Asterisk is an Open Source PBX and telephony toolkit. It is, in a
sense, middleware between Internet and telephony channels on the bottom,
and Internet and telephony applications at the top. For more information
@@ -51,15 +51,13 @@ ANY special hardware, not even a soundcard) to install and run Asterisk.
* All Wildcard (tm) products from Digium (www.digium.com)
* QuickNet Internet PhoneJack and LineJack (http://www.quicknet.net)
* any full duplex sound card supported by ALSA or OSS
* any ISDN card supported by mISDN on Linux (BRI)
* The Xorcom AstriBank channel bank
* VoiceTronix OpenLine products
The are several drivers for ISDN BRI cards available from third party sources.
Check the voip-info.org wiki for more information on chan_capi and
Check the voip-info.org wiki for more information on chan_capi, chan_misdn and
zaphfc.
* UPGRADING FROM AN EARLIER VERSION
* UPGRADING FROM VERSION 1.0
If you are updating from a previous version of Asterisk, make sure you
read the UPGRADE.txt file in the source directory. There are some files
@@ -84,31 +82,14 @@ On many distributions, these files are installed by packages with names like
So let's proceed:
1) Read this README file.
There are more documents than this one in the doc/ directory.
You may also want to check the configuration files that contain
examples and reference guides. They are all in the configs/
directory.
2) Run "./configure"
Execute the configure script to guess values for system-dependent
variables used during compilation.
3) Run "make menuselect" [optional]
This is needed if you want to select the modules that will be
compiled and to check modules dependencies.
4) Run "make"
1) Run "make"
Assuming the build completes successfully:
5) Run "make install"
2) Run "make install"
Each time you update or checkout from the repository, you are strongly
encouraged to ensure all previous object files are removed to avoid internal
Each time you update or checkout from CVS, you are strongly encouraged
to ensure all previous object files are removed to avoid internal
inconsistency in Asterisk. Normally, this is automatically done with
the presence of the file .cleancount, which increments each time a 'make clean'
is required, and the file .lastclean, which contains the last .cleancount used.
@@ -116,7 +97,7 @@ is required, and the file .lastclean, which contains the last .cleancount used.
If this is your first time working with Asterisk, you may wish to install
the sample PBX, with demonstration extensions, etc. If so, run:
6) "make samples"
3) "make samples"
Doing so will overwrite any existing config files you have.
@@ -159,7 +140,7 @@ they're used only to help make the configuration file easier to
understand, and do not affect how it is actually parsed.
Entries of the form 'variable=value' set the value of some parameter in
asterisk. For example, in chan_dahdi.conf, one might specify:
asterisk. For example, in zapata.conf, one might specify:
switchtype=national
@@ -257,6 +238,3 @@ you're interested in getting more information.
Welcome to the growing worldwide community of Asterisk users!
Mark Spencer
----
Asterisk is a trademark belonging to Digium, inc

22
README.opsound Normal file
View File

@@ -0,0 +1,22 @@
About Hold Music
================
These files were obtained from http://opsound.org, where the authors placed them
under the Creative Commons Attribution-Share Alike 2.5 license, a copy of which
may be found at http://creativecommons.org.
Credits
================
macroform-cold_day - Paul Shuler (Macroform)
paulshuler@gmail.com - http://macroform.bandcamp.com/
macroform-robot_dity - Paul Shuler (Macroform)
paulshuler@gmail.com - http://macroform.bandcamp.com/
macroform-the_simplicity - Paul Shuler (Macroform)
paulshuler@gmail.com - http://macroform.bandcamp.com/
manolo_camp-morning_coffee - Manolo Camp
beatbastard@gmx.net - http://ccmixter.org/people/ManoloCamp
reno_project-system - Reno Project
renoproject@hotmail.com - http://www.jamendo.com/en/album/23661

View File

@@ -28,13 +28,6 @@ The IAX2 protocol supports strong RSA key authentication as well as
AES encryption of voice and signalling. The SIP channel does not
support encryption in this version of Asterisk.
By default, if you have libcap available, Asterisk will try to retain the
CAP_NET_ADMIN capability when running as a non-root user. If you do not need
that capability you may want to configure Asterisk with --without-cap; however,
this will prevent Asterisk from being able to mark high ToS bits under Linux.
More information on CAP_NET_ADMIN is available at:
http://www.lids.org/lids-howto/node48.html
* DIALPLAN SECURITY
First and foremost remember this:
@@ -72,9 +65,3 @@ exten => 6123,Dial(Zap/1)
DON'T FORGET TO TAKE THE DEMO CONTEXT OUT OF YOUR DEFAULT CONTEXT. There
isn't really a security reason, it just will keep people from wanting to
play with your Asterisk setup remotely.
* LOG SECURITY
Please note that the Asterisk log files, as well as information printed to the
Asterisk CLI, may contain sensitive information such as passwords and call
history. Keep this in mind when providing access to these resources.

View File

@@ -1,210 +0,0 @@
=========================================================
=== Information for upgrading from Asterisk 1.0 to 1.2
===
===
=== UPGRADE-1.2.txt -- Upgrade info for 1.0 to 1.2
=== UPGRADE.txt -- Upgrade info for 1.2 to 1.4
=========================================================
Compiling:
* The Asterisk 1.2 source code now uses C language features
supported only by 'modern' C compilers. Generally, this means GCC
version 3.0 or higher, although some GCC 2.96 releases will also
work. Some non-GCC compilers that support C99 and the common GCC
extensions (including anonymous structures and unions) will also
work. All releases of GCC 2.95 do _not_ have the requisite feature
support; systems using that compiler will need to be upgraded to
a more recent compiler release.
Dialplan Expressions:
* The dialplan expression parser (which handles $[ ... ] constructs)
has gone through a major upgrade, but has one incompatible change:
spaces are no longer required around expression operators, including
string comparisons. However, you can now use quoting to keep strings
together for comparison. For more details, please read the
doc/README.variables file, and check over your dialplan for possible
problems.
Agents:
* The default for ackcall has been changed to "no" instead of "yes"
because of a bug which caused the "yes" behavior to generally act like
"no". You may need to adjust the value if your agents behave
differently than you expect with respect to acknowledgement.
* The AgentCallBackLogin application now requires a second '|' before
specifying an extension@context. This is to distinguish the options
string from the extension, so that they do not conflict. See
'show application AgentCallbackLogin' for more details.
Parking:
* Parking behavior has changed slightly; when a parked call times out,
Asterisk will attempt to deliver the call back to the extension that
parked it, rather than the 's' extension. If that extension is busy
or unavailable, the parked call will be lost.
Dialing:
* The Caller*ID of the outbound leg is now the extension that was
called, rather than the Caller*ID of the inbound leg of the call. The
"o" flag for Dial can be used to restore the original behavior if
desired. Note that if you are looking for the originating callerid
from the manager event, there is a new manager event "Dial" which
provides the source and destination channels and callerid.
IAX:
* The naming convention for IAX channels has changed in two ways:
1. The call number follows a "-" rather than a "/" character.
2. The name of the channel has been simplified to IAX2/peer-callno,
rather than IAX2/peer@peer-callno or even IAX2/peer@peer/callno.
SIP:
* The global option "port" in 1.0.X that is used to set which port to
bind to has been changed to "bindport" to be more consistent with
the other channel drivers and to avoid confusion with the "port"
option for users/peers.
* The "Registry" event now uses "Username" rather than "User" for
consistency with IAX.
Applications:
* With the addition of dialplan functions (which operate similarly
to variables), the SetVar application has been renamed to Set.
* The CallerPres application has been removed. Use SetCallerPres
instead. It accepts both numeric and symbolic names.
* The applications GetGroupCount, GetGroupMatchCount, SetGroup, and
CheckGroup have been deprecated in favor of functions. Here is a
table of their replacements:
GetGroupCount([groupname][@category] GROUP_COUNT([groupname][@category]) Set(GROUPCOUNT=${GROUP_COUNT()})
GroupMatchCount(groupmatch[@category]) GROUP_MATCH_COUNT(groupmatch[@category]) Set(GROUPCOUNT=${GROUP_MATCH_COUNT(SIP/.*)})
SetGroup(groupname[@category]) GROUP([category])=groupname Set(GROUP()=test)
CheckGroup(max[@category]) N/A GotoIf($[ ${GROUP_COUNT()} > 5 ]?103)
Note that CheckGroup does not have a direct replacement. There is
also a new function called GROUP_LIST() which will return a space
separated list of all of the groups set on a channel. The GROUP()
function can also return the name of the group set on a channel when
used in a read environment.
* The applications DBGet and DBPut have been deprecated in favor of
functions. Here is a table of their replacements:
DBGet(foo=family/key) Set(foo=${DB(family/key)})
DBPut(family/key=${foo}) Set(DB(family/key)=${foo})
* The application SetLanguage has been deprecated in favor of the
function LANGUAGE().
SetLanguage(fr) Set(LANGUAGE()=fr)
The LANGUAGE function can also return the currently set language:
Set(MYLANG=${LANGUAGE()})
* The applications AbsoluteTimeout, DigitTimeout, and ResponseTimeout
have been deprecated in favor of the function TIMEOUT(timeouttype):
AbsoluteTimeout(300) Set(TIMEOUT(absolute)=300)
DigitTimeout(15) Set(TIMEOUT(digit)=15)
ResponseTimeout(15) Set(TIMEOUT(response)=15)
The TIMEOUT() function can also return the currently set timeouts:
Set(DTIMEOUT=${TIMEOUT(digit)})
* The applications SetCIDName, SetCIDNum, and SetRDNIS have been
deprecated in favor of the CALLERID(datatype) function:
SetCIDName(Joe Cool) Set(CALLERID(name)=Joe Cool)
SetCIDNum(2025551212) Set(CALLERID(number)=2025551212)
SetRDNIS(2024561414) Set(CALLERID(RDNIS)=2024561414)
* The application Record now uses the period to separate the filename
from the format, rather than the colon.
* The application VoiceMail now supports a 'temporary' greeting for each
mailbox. This greeting can be recorded by using option 4 in the
'mailbox options' menu, and 'change your password' option has been
moved to option 5.
* The application VoiceMailMain now only matches the 'default' context if
none is specified in the arguments. (This was the previously
documented behavior, however, we didn't follow that behavior.) The old
behavior can be restored by setting searchcontexts=yes in voicemail.conf.
Queues:
* A queue is now considered empty not only if there are no members but if
none of the members are available (e.g. agents not logged on). To
restore the original behavior, use "leavewhenempty=strict" or
"joinwhenempty=strict" instead of "=yes" for those options.
* It is now possible to use multi-digit extensions in the exit context
for a queue (although you should not have overlapping extensions,
as there is no digit timeout). This means that the EXITWITHKEY event
in queue_log can now contain a key field with more than a single
character in it.
Extensions:
* By default, there is a new option called "autofallthrough" in
extensions.conf that is set to yes. Asterisk 1.0 (and earlier)
behavior was to wait for an extension to be dialed after there were no
more extensions to execute. "autofallthrough" changes this behavior
so that the call will immediately be terminated with BUSY,
CONGESTION, or HANGUP based on Asterisk's best guess. If you are
writing an extension for IVR, you must use the WaitExten application
if "autofallthrough" is set to yes.
AGI:
* AGI scripts did not always get SIGHUP at the end, previously. That
behavior has been fixed. If you do not want your script to terminate
at the end of AGI being called (e.g. on a hangup) then set SIGHUP to
be ignored within your application.
* CallerID is reported with agi_callerid and agi_calleridname instead
of a single parameter holding both.
Music On Hold:
* The preferred format for musiconhold.conf has changed; please see the
sample configuration file for the new format. The existing format
is still supported but will generate warnings when the module is loaded.
chan_modem:
* All the chan_modem channel drivers (aopen, bestdata and i4l) are deprecated
in this release, and will be removed in the next major Asterisk release.
Please migrate to chan_misdn for ISDN interfaces; there is no upgrade
path for aopen and bestdata modem users.
MeetMe:
* The conference application now allows users to increase/decrease their
speaking volume and listening volume (independently of each other and
other users); the 'admin' and 'user' menus have changed, and new sound
files are included with this release. However, if a user calling in
over a Zaptel channel that does NOT have hardware DTMF detection
increases their speaking volume, it is likely they will no longer be
able to enter/exit the menu or make any further adjustments, as the
software DTMF detector will not be able to recognize the DTMF coming
from their device.
GetVar Manager Action:
* Previously, the behavior of the GetVar manager action reported the value
of a variable in the following manner:
> name: value
This has been changed to a manner similar to the SetVar action and is now
> Variable: name
> Value: value

View File

@@ -1,500 +1,205 @@
=========================================================
=== Information for upgrading from Asterisk 1.2 to 1.4
===
===
=== UPGRADE-1.2.txt -- Upgrade info for 1.0 to 1.2
=== UPGRADE.txt -- Upgrade info for 1.2 to 1.4
Information for Upgrading From Previous Asterisk Releases
=========================================================
Build Process (configure script):
Compiling:
Asterisk now uses an autoconf-generated configuration script to learn how it
should build itself for your system. As it is a standard script, running:
* The Asterisk 1.2 source code now uses C language features
supported only by 'modern' C compilers. Generally, this means GCC
version 3.0 or higher, although some GCC 2.96 releases will also
work. Some non-GCC compilers that support C99 and the common GCC
extensions (including anonymous structures and unions) will also
work. All releases of GCC 2.95 do _not_ have the requisite feature
support; systems using that compiler will need to be upgraded to
a more recent compiler release.
$ ./configure --help
Dialplan Expressions:
will show you all the options available. This script can be used to tell the
build process what libraries you have on your system (if it cannot find them
automatically), which libraries you wish to have ignored even though they may
be present, etc.
* The dialplan expression parser (which handles $[ ... ] constructs)
has gone through a major upgrade, but has one incompatible change:
spaces are no longer required around expression operators, including
string comparisons. However, you can now use quoting to keep strings
together for comparison. For more details, please read the
doc/README.variables file, and check over your dialplan for possible
problems.
You must run the configure script before Asterisk will build, although it will
attempt to automatically run it for you with no options specified; for most
users, that will result in a similar build to what they would have had before
the configure script was added to the build process (except for having to run
'make' again after the configure script is run). Note that the configure script
does NOT need to be re-run just to rebuild Asterisk; you only need to re-run it
when your system configuration changes or you wish to build Asterisk with
different options.
Agents:
Build Process (module selection):
* The default for ackcall has been changed to "no" instead of "yes"
because of a bug which caused the "yes" behavior to generally act like
"no". You may need to adjust the value if your agents behave
differently than you expect with respect to acknowledgement.
The Asterisk source tree now includes a basic module selection and build option
selection tool called 'menuselect'. Run 'make menuselect' to make your choices.
In this tool, you can disable building of modules that you don't care about,
turn on/off global options for the build and see which modules will not
(and cannot) be built because your system does not have the required external
dependencies installed.
* The AgentCallBackLogin application now requires a second '|' before
specifying an extension@context. This is to distinguish the options
string from the extension, so that they do not conflict. See
'show application AgentCallbackLogin' for more details.
The resulting file from menuselect is called 'menuselect.makeopts'. Note that
the resulting menuselect.makeopts file generally contains which modules *not*
to build. The modules listed in this file indicate which modules have unmet
dependencies, a present conflict, or have been disabled by the user in the
menuselect interface. Compiler Flags can also be set in the menuselect
interface. In this case, the resulting file contains which CFLAGS are in use,
not which ones are not in use.
Parking:
If you would like to save your choices and have them applied against all
builds, the file can be copied to '~/.asterisk.makeopts' or
'/etc/asterisk.makeopts'.
* Parking behavior has changed slightly; when a parked call times out,
Asterisk will attempt to deliver the call back to the extension that
parked it, rather than the 's' extension. If that extension is busy
or unavailable, the parked call will be lost.
Build Process (Makefile targets):
Dialing:
The 'valgrind' and 'dont-optimize' targets have been removed; their functionality
is available by enabling the DONT_OPTIMIZE setting in the 'Compiler Flags' menu
in the menuselect tool.
* The Caller*ID of the outbound leg is now the extension that was
called, rather than the Caller*ID of the inbound leg of the call. The
"o" flag for Dial can be used to restore the original behavior if
desired. Note that if you are looking for the originating callerid
from the manager event, there is a new manager event "Dial" which
provides the source and destination channels and callerid.
It is now possible to run most make targets against a single subdirectory; from
the top level directory, for example, 'make channels' will run 'make all' in the
'channels' subdirectory. This also is true for 'clean', 'distclean' and 'depend'.
IAX:
Sound (prompt) and Music On Hold files:
* The naming convention for IAX channels has changed in two ways:
1. The call number follows a "-" rather than a "/" character.
2. The name of the channel has been simplified to IAX2/peer-callno,
rather than IAX2/peer@peer-callno or even IAX2/peer@peer/callno.
Beginning with Asterisk 1.4, the sound files and music on hold files supplied for
use with Asterisk have been replaced with new versions produced from high quality
master recordings, and are available in three languages (English, French and
Spanish) and in five formats (WAV (uncompressed), mu-Law, a-Law, GSM and G.729).
In addition, the music on hold files provided by FreePlay Music are now available
in the same five formats, but no longer available in MP3 format.
SIP:
The Asterisk 1.4 tarball packages will only include English prompts in GSM format,
(as were supplied with previous releases) and the FreePlay MOH files in WAV format.
All of the other variations can be installed by running 'make menuselect' and
selecting the packages you wish to install; when you run 'make install', those
packages will be downloaded and installed along with the standard files included
in the tarball.
* The global option "port" in 1.0.X that is used to set which port to
bind to has been changed to "bindport" to be more consistent with
the other channel drivers and to avoid confusion with the "port"
option for users/peers.
If for some reason you expect to not have Internet access at the time you will be
running 'make install', you can make your package selections using menuselect and
then run 'make sounds' to download (only) the sound packages; this will leave the
sound packages in the 'sounds' subdirectory to be used later during installation.
WARNING: Asterisk 1.4 supports a new layout for sound files in multiple languages;
instead of the alternate-language files being stored in subdirectories underneath
the existing files (for French, that would be digits/fr, letters/fr, phonetic/fr,
etc.) the new layout creates one directory under /var/lib/asterisk/sounds for the
language itself, then places all the sound files for that language under that
directory and its subdirectories. This is the layout that will be created if you
select non-English languages to be installed via menuselect, HOWEVER Asterisk does
not default to this layout and will not find the files in the places it expects them
to be. If you wish to use this layout, make sure you put 'languageprefix=yes' in your
/etc/asterisk/asterisk.conf file, so that Asterisk will know how the files were
installed.
PBX Core:
* The (very old and undocumented) ability to use BYEXTENSION for dialing
instead of ${EXTEN} has been removed.
* Builtin (res_features) transfer functionality attempts to use the context
defined in TRANSFER_CONTEXT variable of the transferer channel first. If
not set, it uses the transferee variable. If not set in any channel, it will
attempt to use the last non macro context. If not possible, it will default
to the current context.
* The autofallthrough setting introduced in Asterisk 1.2 now defaults to 'yes';
if your dialplan relies on the ability to 'run off the end' of an extension
and wait for a new extension without using WaitExten() to accomplish that,
you will need set autofallthrough to 'no' in your extensions.conf file.
Command Line Interface:
* 'show channels concise', designed to be used by applications that will parse
its output, previously used ':' characters to separate fields. However, some
of those fields can easily contain that character, making the output not
parseable. The delimiter has been changed to '!'.
* The "Registry" event now uses "Username" rather than "User" for
consistency with IAX.
Applications:
* In previous Asterisk releases, many applications would jump to priority n+101
to indicate some kind of status or error condition. This functionality was
marked deprecated in Asterisk 1.2. An option to disable it was provided with
the default value set to 'on'. The default value for the global priority
jumping option is now 'off'.
* The applications Cut, Sort, DBGet, DBPut, SetCIDNum, SetCIDName, SetRDNIS,
AbsoluteTimeout, DigitTimeout, ResponseTimeout, SetLanguage, GetGroupCount,
and GetGroupMatchCount were all deprecated in version 1.2, and therefore have
been removed in this version. You should use the equivalent dialplan
function in places where you have previously used one of these applications.
* The application SetGlobalVar has been deprecated. You should replace uses
of this application with the following combination of Set and GLOBAL():
Set(GLOBAL(name)=value). You may also access global variables exclusively by
using the GLOBAL() dialplan function, instead of relying on variable
interpolation falling back to globals when no channel variable is set.
* The application SetVar has been renamed to Set. The syntax SetVar was marked
deprecated in version 1.2 and is no longer recognized in this version. The
use of Set with multiple argument pairs has also been deprecated. Please
separate each name/value pair into its own dialplan line.
* app_read has been updated to use the newer options codes, using "skip" or
"noanswer" will not work. Use s or n. Also there is a new feature i, for
using indication tones, so typing in skip would give you unexpected results.
* OSPAuth is added to authenticate OSP tokens in in_bound call setup messages.
* The CONNECT event in the queue_log from app_queue now has a second field
in addition to the holdtime field. It contains the unique ID of the
queue member channel that is taking the call. This is useful when trying
to link recording filenames back to a particular call from the queue.
* The old/current behavior of app_queue has a serial type behavior
in that the queue will make all waiting callers wait in the queue
even if there is more than one available member ready to take
calls until the head caller is connected with the member they
were trying to get to. The next waiting caller in line then
becomes the head caller, and they are then connected with the
next available member and all available members and waiting callers
waits while this happens. This cycle continues until there are
no more available members or waiting callers, whichever comes first.
The new behavior, enabled by setting autofill=yes in queues.conf
either at the [general] level to default for all queues or
to set on a per-queue level, makes sure that when the waiting
callers are connecting with available members in a parallel fashion
until there are no more available members or no more waiting callers,
whichever comes first. This is probably more along the lines of how
one would expect a queue should work and in most cases, you will want
to enable this new behavior. If you do not specify or comment out this
option, it will default to "no" to keep backward compatability with the old
behavior.
* Queues depend on the channel driver reporting the proper state
for each member of the queue. To get proper signalling on
queue members that use the SIP channel driver, you need to
enable a call limit (could be set to a high value so it
is not put into action) and also make sure that both inbound
and outbound calls are accounted for.
Example:
[general]
limitonpeer = yes
[peername]
type=friend
call-limit=10
* The app_queue application now has the ability to use MixMonitor to
record conversations queue members are having with queue callers. Please
see configs/queues.conf.sample for more information on this option.
* The app_queue application strategy called 'roundrobin' has been deprecated
for this release. Users are encouraged to use 'rrmemory' instead, since it
provides more 'true' round-robin call delivery. For the Asterisk 1.6 release,
'rrmemory' will be renamed 'roundrobin'.
* The app_queue application option called 'monitor-join' has been deprecated
for this release. Users are encouraged to use 'monitor-type=mixmonitor' instead,
since it provides the same functionality but is not dependent on soxmix or some
other external program in order to mix the audio.
* app_meetme: The 'm' option (monitor) is renamed to 'l' (listen only), and
the 'm' option now provides the functionality of "initially muted".
In practice, most existing dialplans using the 'm' flag should not notice
any difference, unless the keypad menu is enabled, allowing the user
to unmute themsleves.
* ast_play_and_record would attempt to cancel the recording if a DTMF
'0' was received. This behavior was not documented in most of the
applications that used ast_play_and_record and the return codes from
ast_play_and_record weren't checked for properly.
ast_play_and_record has been changed so that '0' no longer cancels a
recording. If you want to allow DTMF digits to cancel an
in-progress recording use ast_play_and_record_full which allows you
to specify which DTMF digits can be used to accept a recording and
which digits can be used to cancel a recording.
* ast_app_messagecount has been renamed to ast_app_inboxcount. There is now a
new ast_app_messagecount function which takes a single context/mailbox/folder
mailbox specification and returns the message count for that folder only.
This addresses the deficiency of not being able to count the number of
messages in folders other than INBOX and Old.
* The exit behavior of the AGI applications has changed. Previously, when
a connection to an AGI server failed, the application would cause the channel
to immediately stop dialplan execution and hangup. Now, the only time that
the AGI applications will cause the channel to stop dialplan execution is
when the channel itself requests hangup. The AGI applications now set an
AGISTATUS variable which will allow you to find out whether running the AGI
was successful or not.
Previously, there was no way to handle the case where Asterisk was unable to
locally execute an AGI script for some reason. In this case, dialplan
execution will continue as it did before, but the AGISTATUS variable will be
set to "FAILURE".
A locally executed AGI script can now exit with a non-zero exit code and this
failure will be detected by Asterisk. If an AGI script exits with a non-zero
exit code, the AGISTATUS variable will be set to "FAILURE" as opposed to
"SUCCESS".
* app_voicemail: The ODBC_STORAGE capability now requires the extended table format
previously used only by EXTENDED_ODBC_STORAGE. This means that you will need to update
your table format using the schema provided in doc/odbcstorage.txt
* app_waitforsilence: Fixes have been made to this application which changes the
default behavior with how quickly it returns. You can maintain "old-style" behavior
with the addition/use of a third "timeout" parameter.
Please consult the application documentation and make changes to your dialplan
if appropriate.
Manager:
* After executing the 'status' manager action, the "Status" manager events
included the header "CallerID:" which was actually only the CallerID number,
and not the full CallerID string. This header has been renamed to
"CallerIDNum". For compatibility purposes, the CallerID parameter will remain
until after the release of 1.4, when it will be removed. Please use the time
during the 1.4 release to make this transition.
* The AgentConnect event now has an additional field called "BridgedChannel"
which contains the unique ID of the queue member channel that is taking the
call. This is useful when trying to link recording filenames back to
a particular call from the queue.
* app_userevent has been modified to always send Event: UserEvent with the
additional header UserEvent: <userspec>. Also, the Channel and UniqueID
headers are not automatically sent, unless you specify them as separate
arguments. Please see the application help for the new syntax.
* app_meetme: Mute and Unmute events are now reported via the Manager API.
Native Manager API commands MeetMeMute and MeetMeUnmute are provided, which
are easier to use than "Action Command:". The MeetMeStopTalking event has
also been deprecated in favor of the already existing MeetmeTalking event
with a "Status" of "on" or "off" added.
* OriginateFailure and OriginateSuccess events were replaced by event
OriginateResponse with a header named "Response" to indicate success or
failure
Variables:
* The builtin variables ${CALLERID}, ${CALLERIDNAME}, ${CALLERIDNUM},
${CALLERANI}, ${DNID}, ${RDNIS}, ${DATETIME}, ${TIMESTAMP}, ${ACCOUNTCODE},
and ${LANGUAGE} have all been deprecated in favor of their related dialplan
functions. You are encouraged to move towards the associated dialplan
function, as these variables will be removed in a future release.
* The CDR-CSV variables uniqueid, userfield, and basing time on GMT are now
adjustable from cdr.conf, instead of recompiling.
* OSP applications exports several new variables, ${OSPINHANDLE},
${OSPOUTHANDLE}, ${OSPINTOKEN}, ${OSPOUTTOKEN}, ${OSPCALLING},
${OSPINTIMELIMIT}, and ${OSPOUTTIMELIMIT}
* Builtin transfer functionality sets the variable ${TRANSFERERNAME} in the new
created channel. This variables holds the channel name of the transferer.
* The dial plan variable PRI_CAUSE will be removed from future versions
of Asterisk.
It is replaced by adding a cause value to the hangup() application.
Functions:
* The function ${CHECK_MD5()} has been deprecated in favor of using an
expression: $[${MD5(<string>)} = ${saved_md5}].
* The 'builtin' functions that used to be combined in pbx_functions.so are
now built as separate modules. If you are not using 'autoload=yes' in your
modules.conf file then you will need to explicitly load the modules that
contain the functions you want to use.
* The ENUMLOOKUP() function with the 'c' option (for counting the number of
records), but the lookup fails to match any records, the returned value will
now be "0" instead of blank.
* The REALTIME() function is now available in version 1.4 and app_realtime has
been deprecated in favor of the new function. app_realtime will be removed
completely with the version 1.6 release so please take the time between
releases to make any necessary changes
* The QUEUEAGENTCOUNT() function has been deprecated in favor of
QUEUE_MEMBER_COUNT().
The IAX2 channel:
* It is possible that previous configurations depended on the order in which
peers and users were specified in iax.conf for forcing the order in which
chan_iax2 matched against them. This behavior is going away and is considered
deprecated in this version. Avoid having ambiguous peer and user entries and
to make things easy on yourself, always set the "username" option for users
so that the remote end can match on that exactly instead of trying to infer
which user you want based on host.
If you would like to go ahead and use the new behavior which doesn't use the
order in the config file to influence matching order, then change the
MAX_PEER_BUCKETS define in chan_iax2.c to a value greater than one. An
example is provided there. By changing this, you will get *much* better
performance on systems that do a lot of peer and user lookups as they will be
stored in memory in a much more efficient manner.
* The "mailboxdetail" option has been deprecated. Previously, if this option
was not enabled, the 2 byte MSGCOUNT information element would be set to all
1's to indicate there there is some number of messages waiting. With this
option enabled, the number of new messages were placed in one byte and the
number of old messages are placed in the other. This is now the default
(and the only) behavior.
The SIP channel:
* The "incominglimit" setting is replaced by the "call-limit" setting in
sip.conf.
* OSP support code is removed from SIP channel to OSP applications. ospauth
option in sip.conf is removed to osp.conf as authpolicy. allowguest option
in sip.conf cannot be set as osp anymore.
* The Asterisk RTP stack has been changed in regards to RFC2833 reception
and transmission. Packets will now be sent with proper duration instead of all
at once. If you are receiving calls from a pre-1.4 Asterisk installation you
will want to turn on the rfc2833compensate option. Without this option your
DTMF reception may act poorly.
* The $SIPUSERAGENT dialplan variable is deprecated and will be removed
in coming versions of Asterisk. Please use the dialplan function
SIPCHANINFO(useragent) instead.
* The ALERT_INFO dialplan variable is deprecated and will be removed
in coming versions of Asterisk. Please use the dialplan application
sipaddheader() to add the "Alert-Info" header to the outbound invite.
* The "canreinvite" option has changed. canreinvite=yes used to disable
re-invites if you had NAT=yes. In 1.4, you need to set canreinvite=nonat
to disable re-invites when NAT=yes. This is propably what you want.
The settings are now: "yes", "no", "nonat", "update". Please consult
sip.conf.sample for detailed information.
The Zap channel:
* Support for MFC/R2 has been removed, as it has not been functional for some
time and it has no maintainer.
The Agent channel:
* Callback mode (AgentCallbackLogin) is now deprecated, since the entire function
it provided can be done using dialplan logic, without requiring additional
channel and module locks (which frequently caused deadlocks). An example of
how to do this using AEL dialplan is in doc/queues-with-callback-members.txt.
The G726-32 codec:
* It has been determined that previous versions of Asterisk used the wrong codeword
packing order for G726-32 data. This version supports both available packing orders,
and can transcode between them. It also now selects the proper order when
negotiating with a SIP peer based on the codec name supplied in the SDP. However,
there are existing devices that improperly request one order and then use another;
Sipura and Grandstream ATAs are known to do this, and there may be others. To
be able to continue to use these devices with this version of Asterisk and the
G726-32 codec, a configuration parameter called 'g726nonstandard' has been added
to sip.conf, so that Asterisk can use the packing order expected by the device (even
though it requested a different order). In addition, the internal format number for
G726-32 has been changed, and the old number is now assigned to AAL2-G726-32. The
result of this is that this version of Asterisk will be able to interoperate over
IAX2 with older versions of Asterisk, as long as this version is told to allow
'g726aal2' instead of 'g726' as the codec for the call.
Installation:
* On BSD systems, the installation directories have changed to more "FreeBSDish"
directories. On startup, Asterisk will look for the main configuration in
/usr/local/etc/asterisk/asterisk.conf
If you have an old installation, you might want to remove the binaries and
move the configuration files to the new locations. The following directories
are now default:
ASTLIBDIR /usr/local/lib/asterisk
ASTVARLIBDIR /usr/local/share/asterisk
ASTETCDIR /usr/local/etc/asterisk
ASTBINDIR /usr/local/bin/asterisk
ASTSBINDIR /usr/local/sbin/asterisk
Music on Hold:
* The music on hold handling has been changed in some significant ways in hopes
to make it work in a way that is much less confusing to users. Behavior will
not change if the same configuration is used from older versions of Asterisk.
However, there are some new configuration options that will make things work
in a way that makes more sense.
Previously, many of the channel drivers had an option called "musicclass" or
something similar. This option set what music on hold class this channel
would *hear* when put on hold. Some people expected (with good reason) that
this option was to configure what music on hold class to play when putting
the bridged channel on hold. This option has now been deprecated.
Two new music on hold related configuration options for channel drivers have
been introduced. Some channel drivers support both options, some just one,
and some support neither of them. Check the sample configuration files to see
which options apply to which channel driver.
The "mohsuggest" option specifies which music on hold class to suggest to the
bridged channel when putting them on hold. The only way that this class can
be overridden is if the bridged channel has a specific music class set that
was done in the dialplan using Set(CHANNEL(musicclass)=something).
The "mohinterpret" option is similar to the old "musicclass" option. It
specifies which music on hold class this channel would like to listen to when
put on hold. This music class is only effective if this channel has no music
class set on it from the dialplan and the bridged channel putting this one on
hold had no "mohsuggest" setting.
The IAX2 and Zap channel drivers have an additional feature for the
"mohinterpret" option. If this option is set to "passthrough", then these
channel drivers will pass through the HOLD message in signalling instead of
starting music on hold on the channel. An example for how this would be
useful is in an enterprise network of Asterisk servers. When one phone on one
server puts a phone on a different server on hold, the remote server will be
responsible for playing the hold music to its local phone that was put on
hold instead of the far end server across the network playing the music.
CDR Records:
* The behavior of the "clid" field of the CDR has always been that it will
contain the callerid ANI if it is set, or the callerid number if ANI was not
set. When using the "callerid" option for various channel drivers, some
would set ANI and some would not. This has been cleared up so that all
channel drivers set ANI. If you would like to change the callerid number
on the channel from the dialplan and have that change also show up in the
CDR, then you *must* set CALLERID(ANI) as well as CALLERID(num).
API:
* There are some API functions that were not previously prefixed with the 'ast_'
prefix but now are; these include the ADSI, ODBC and AGI interfaces. If you
have a module that uses the services provided by res_adsi, res_odbc, or
res_agi, you will need to add ast_ prefixes to the functions that you call
from those modules.
Formats:
* format_wav: The GAIN preprocessor definition has been changed from 2 to 0
in Asterisk 1.4. This change was made in response to user complaints of
choppiness or the clipping of loud signal peaks. The GAIN preprocessor
definition will be retained in Asterisk 1.4, but will be removed in a
future release. The use of GAIN for the increasing of voicemail message
volume should use the 'volgain' option in voicemail.conf
iLBC Codec:
* Previously, the Asterisk source code distribution included the iLBC
encoder/decoder source code, from Global IP Solutions
(http://www.gipscorp.com). This code is not licensed for
distribution, and thus has been removed from the Asterisk source
code distribution. If you wish to use codec_ilbc to support iLBC
channels in Asterisk, you can run the contrib/scripts/get_ilbc_source.sh
script to download the source and put it in the proper place in
the Asterisk build tree. Once that is done you can follow your normal
steps of building Asterisk. You will need to run 'menuselect' and enable
the iLBC codec in the 'Codec Translators' category.
* With the addition of dialplan functions (which operate similarly
to variables), the SetVar application has been renamed to Set.
* The CallerPres application has been removed. Use SetCallerPres
instead. It accepts both numeric and symbolic names.
* The applications GetGroupCount, GetGroupMatchCount, SetGroup, and
CheckGroup have been deprecated in favor of functions. Here is a
table of their replacements:
GetGroupCount([groupname][@category] GROUP_COUNT([groupname][@category]) Set(GROUPCOUNT=${GROUP_COUNT()})
GroupMatchCount(groupmatch[@category]) GROUP_MATCH_COUNT(groupmatch[@category]) Set(GROUPCOUNT=${GROUP_MATCH_COUNT(SIP/.*)})
SetGroup(groupname[@category]) GROUP([category])=groupname Set(GROUP()=test)
CheckGroup(max[@category]) N/A GotoIf($[ ${GROUP_COUNT()} > 5 ]?103)
Note that CheckGroup does not have a direct replacement. There is
also a new function called GROUP_LIST() which will return a space
separated list of all of the groups set on a channel. The GROUP()
function can also return the name of the group set on a channel when
used in a read environment.
* The applications DBGet and DBPut have been deprecated in favor of
functions. Here is a table of their replacements:
DBGet(foo=family/key) Set(foo=${DB(family/key)})
DBPut(family/key=${foo}) Set(DB(family/key)=${foo})
* The application SetLanguage has been deprecated in favor of the
function LANGUAGE().
SetLanguage(fr) Set(LANGUAGE()=fr)
The LANGUAGE function can also return the currently set language:
Set(MYLANG=${LANGUAGE()})
* The applications AbsoluteTimeout, DigitTimeout, and ResponseTimeout
have been deprecated in favor of the function TIMEOUT(timeouttype):
AbsoluteTimeout(300) Set(TIMEOUT(absolute)=300)
DigitTimeout(15) Set(TIMEOUT(digit)=15)
ResponseTimeout(15) Set(TIMEOUT(response)=15)
The TIMEOUT() function can also return the currently set timeouts:
Set(DTIMEOUT=${TIMEOUT(digit)})
* The applications SetCIDName, SetCIDNum, and SetRDNIS have been
deprecated in favor of the CALLERID(datatype) function:
SetCIDName(Joe Cool) Set(CALLERID(name)=Joe Cool)
SetCIDNum(2025551212) Set(CALLERID(number)=2025551212)
SetRDNIS(2024561414) Set(CALLERID(RDNIS)=2024561414)
* The application Record now uses the period to separate the filename
from the format, rather than the colon.
* The application VoiceMail now supports a 'temporary' greeting for each
mailbox. This greeting can be recorded by using option 4 in the
'mailbox options' menu, and 'change your password' option has been
moved to option 5.
* The application VoiceMailMain now only matches the 'default' context if
none is specified in the arguments. (This was the previously
documented behavior, however, we didn't follow that behavior.) The old
behavior can be restored by setting searchcontexts=yes in voicemail.conf.
Queues:
* A queue is now considered empty not only if there are no members but if
none of the members are available (e.g. agents not logged on). To
restore the original behavior, use "leavewhenempty=strict" or
"joinwhenempty=strict" instead of "=yes" for those options.
* It is now possible to use multi-digit extensions in the exit context
for a queue (although you should not have overlapping extensions,
as there is no digit timeout). This means that the EXITWITHKEY event
in queue_log can now contain a key field with more than a single
character in it.
Extensions:
* By default, there is a new option called "autofallthrough" in
extensions.conf that is set to yes. Asterisk 1.0 (and earlier)
behavior was to wait for an extension to be dialed after there were no
more extensions to execute. "autofallthrough" changes this behavior
so that the call will immediately be terminated with BUSY,
CONGESTION, or HANGUP based on Asterisk's best guess. If you are
writing an extension for IVR, you must use the WaitExten application
if "autofallthrough" is set to yes.
AGI:
* AGI scripts did not always get SIGHUP at the end, previously. That
behavior has been fixed. If you do not want your script to terminate
at the end of AGI being called (e.g. on a hangup) then set SIGHUP to
be ignored within your application.
* CallerID is reported with agi_callerid and agi_calleridname instead
of a single parameter holding both.
Music On Hold:
* The preferred format for musiconhold.conf has changed; please see the
sample configuration file for the new format. The existing format
is still supported but will generate warnings when the module is loaded.
chan_modem:
* All the chan_modem channel drivers (aopen, bestdata and i4l) are deprecated
in this release, and will be removed in the next major Asterisk release.
Please migrate to chan_misdn for ISDN interfaces; there is no upgrade
path for aopen and bestdata modem users.
MeetMe:
* The conference application now allows users to increase/decrease their
speaking volume and listening volume (independently of each other and
other users); the 'admin' and 'user' menus have changed, and new sound
files are included with this release. However, if a user calling in
over a Zaptel channel that does NOT have hardware DTMF detection
increases their speaking volume, it is likely they will no longer be
able to enter/exit the menu or make any further adjustments, as the
software DTMF detector will not be able to recognize the DTMF coming
from their device.
GetVar Manager Action:
* Previously, the behavior of the GetVar manager action reported the value
of a variable in the following manner:
> name: value
This has been changed to a manner similar to the SetVar action and is now
> Variable: name
> Value: value

View File

@@ -1,105 +0,0 @@
=========================================================
=== Information for upgrading from Zaptel to DAHDI ===
=========================================================
As announced in early 2008, Digium is renaming the Zaptel telephony
interface project to DAHDI (Digium Asterisk Hardware Device Interface)
to accommodate the desires of the owner of the Zaptel trademark for
telephony purposes.
This version of Asterisk can be built using either Zaptel or DAHDI,
and has many changes to make the use of DAHDI as easy as possible for
existing users with dialplans, CDR parsers, AMI applications, and
others that expect Zaptel to be in use.
First, the modules that directly use services from Zaptel/DAHDI have been
renamed; the new names are:
chan_zap.so -> chan_dahdi.so
app_zapbarge.so -> app_dahdibarge.so
app_zapras.so -> app_dahdiras.so
app_zapscan.so -> app_dahdiscan.so
codec_zap.so -> codec_dahdi.so
However, in spite of the file name changes, the channels and
applications provided by these modules can still be used with 'Zap'
style names; see below for more information.
Second, there are have been a number of efforts made to ensure that
existing systems will not have to have any major configuration changes
made solely because Asterisk was built against DAHDI instead of
Zaptel. This includes:
chan_dahdi.so:
This module will determine which channel name ('Zap' or 'DAHDI')
should be used for incoming and outgoing channels based on the
build-time choice of telephony drivers. However, if you wish to
continue using the 'Zap' channel name even though you built Asterisk
against the DAHDI drivers, you can add the following line to the
[options] section of your /etc/asterisk/asterisk.conf file:
dahdichanname = no
All CLI commands that begin with 'zap' are now available as 'dahdi'
commands as well; the 'zap' variants will report that they are
deprecated the first time you use each one in an Asterisk instance,
but they will otherwise operate just as they did in previous versions.
All Asterisk Manager Interface (AMI) actions that begin with 'Zap'
are also available with 'DAHDI' prefixes.
The ZapSendKeypadFacility dialplan application is now available as
DAHDISendKeypadFacility as well; the Zap variant will report a deprecation
warning but will otherwise operate as it did it in previous
versions.
The configuration for the channel driver will be read from
/etc/asterisk/chan_dahdi.conf unless 'dahdichanname' has been set to
'no' in asterisk.conf; if that is done, then the configuration will
be read from /etc/asterisk/zapata.conf, just as it was in previous
versions.
app_dahdibarge.so:
The ZapBarge application is now available as DAHDIBarge as well; the
ZapBarge variant will report a deprecation warning when used, but
will otherwise operate as it did in previous versions. Regardless of
which application name is used, the application will restrict itself
to channels of the proper type, based on the 'dahdichanname' setting
in asterisk.conf.
app_dahdiras.so:
The ZapRAS application is now available as DAHDIRAS as well; the
ZapRAS variant will report a deprecation warning when used, but will
otherwise operate as it did in previous versions. Regardless of
which application name is used, the application will restrict itself
to channels of the proper type, based on the 'dahdichanname' setting
in asterisk.conf.
app_dahdiscan.so:
The ZapScan application is now available as DAHDIScan as well; the
ZapScan variant will report a deprecation warning when used, but will
otherwise operate as it did in previous versions. Regardless of
which application name is used, the application will restrict itself
to channels of the proper type, based on the 'dahdichanname' setting
in asterisk.conf.
app_flash.so:
This application has not had any name changes, but will report its
usage (via 'show application flash') as being for either DAHDI or
Zaptel channels based on the 'dahdichanname' setting in
asterisk.conf.
app_chanspy.so:
This application will transparently create 'DAHDI' or 'Zap' channels
as needed, based on the 'dahdichanname' setting in asterisk.conf.
app_meetme.so:
This application will transparently create 'DAHDI' or 'Zap' channels
as needed, based on the 'dahdichanname' setting in asterisk.conf.

View File

@@ -1,7 +1,7 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2006, Digium, Inc.
* Copyright (C) 1999 - 2005, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
@@ -19,14 +19,9 @@
/*! \file
*
* \brief Various sorts of access control
*
* \author Mark Spencer <markster@digium.com>
*
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -39,20 +34,18 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <sys/socket.h>
#include <netdb.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <sys/ioctl.h>
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__Darwin__)
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)
#include <fcntl.h>
#include <net/route.h>
#endif
#if defined(SOLARIS)
#include <sys/sockio.h>
#include <net/if.h>
#elif defined(HAVE_GETIFADDRS)
#include <ifaddrs.h>
#endif
/* netinet/ip.h may not define the following (See RFCs 791 and 1349) */
@@ -64,6 +57,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define IPTOS_MINCOST IPTOS_LOWCOST
#endif
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/acl.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
@@ -71,6 +68,11 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/srv.h"
#include "asterisk/compat.h"
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)
AST_MUTEX_DEFINE_STATIC(routeseq_lock);
#endif
struct ast_ha {
/* Host access rule */
@@ -81,179 +83,18 @@ struct ast_ha {
};
/* Default IP - if not otherwise set, don't breathe garbage */
static struct in_addr __ourip = { .s_addr = 0x00000000, };
static struct in_addr __ourip = { 0x00000000 };
struct my_ifreq {
char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "eth0", "ppp0", etc. */
struct sockaddr_in ifru_addr;
};
#if (!defined(SOLARIS) && !defined(HAVE_GETIFADDRS))
static int get_local_address(struct in_addr *ourip)
{
return -1;
}
#else
static void score_address(const struct sockaddr_in *sin, struct in_addr *best_addr, int *best_score)
{
const char *address;
int score;
address = ast_inet_ntoa(sin->sin_addr);
/* RFC 1700 alias for the local network */
if (address[0] == '0')
score = -25;
/* RFC 1700 localnet */
else if (strncmp(address, "127", 3) == 0)
score = -20;
/* RFC 1918 non-public address space */
else if (strncmp(address, "10.", 3) == 0)
score = -5;
/* RFC 1918 non-public address space */
else if (strncmp(address, "172", 3) == 0) {
/* 172.16.0.0 - 172.19.255.255, but not 172.160.0.0 - 172.169.255.255 */
if (address[4] == '1' && address[5] >= '6' && address[6] == '.')
score = -5;
/* 172.20.0.0 - 172.29.255.255, but not 172.200.0.0 - 172.255.255.255 nor 172.2.0.0 - 172.2.255.255 */
else if (address[4] == '2' && address[6] == '.')
score = -5;
/* 172.30.0.0 - 172.31.255.255 */
else if (address[4] == '3' && address[5] <= '1')
score = -5;
/* All other 172 addresses are public */
else
score = 0;
/* RFC 2544 Benchmark test range */
} else if (strncmp(address, "198.1", 5) == 0 && address[5] >= '8' && address[6] == '.')
score = -10;
/* RFC 1918 non-public address space */
else if (strncmp(address, "192.168", 7) == 0)
score = -5;
/* RFC 3330 Zeroconf network */
else if (strncmp(address, "169.254", 7) == 0)
/*!\note Better score than a test network, but not quite as good as RFC 1918
* address space. The reason is that some Linux distributions automatically
* configure a Zeroconf address before trying DHCP, so we want to prefer a
* DHCP lease to a Zeroconf address.
*/
score = -10;
/* RFC 3330 Test network */
else if (strncmp(address, "192.0.2.", 8) == 0)
score = -15;
/* Every other address should be publically routable */
else
score = 0;
if (score > *best_score) {
*best_score = score;
memcpy(best_addr, &sin->sin_addr, sizeof(*best_addr));
}
}
static int get_local_address(struct in_addr *ourip)
{
int s, res = -1;
#ifdef SOLARIS
struct lifreq *ifr = NULL;
struct lifnum ifn;
struct lifconf ifc;
struct sockaddr_in *sa;
char *buf = NULL;
int bufsz, x;
#endif /* SOLARIS */
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__)
struct ifaddrs *ifap, *ifaphead;
int rtnerr;
const struct sockaddr_in *sin;
#endif /* BSD_OR_LINUX */
struct in_addr best_addr;
int best_score = -100;
memset(&best_addr, 0, sizeof(best_addr));
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__)
rtnerr = getifaddrs(&ifaphead);
if (rtnerr) {
perror(NULL);
return -1;
}
#endif /* BSD_OR_LINUX */
s = socket(AF_INET, SOCK_STREAM, 0);
if (s > 0) {
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__)
for (ifap = ifaphead; ifap; ifap = ifap->ifa_next) {
if (ifap->ifa_addr && ifap->ifa_addr->sa_family == AF_INET) {
sin = (const struct sockaddr_in *) ifap->ifa_addr;
score_address(sin, &best_addr, &best_score);
res = 0;
if (best_score == 0)
break;
}
}
#endif /* BSD_OR_LINUX */
/* There is no reason whatsoever that this shouldn't work on Linux or BSD also. */
#ifdef SOLARIS
/* Get a count of interfaces on the machine */
ifn.lifn_family = AF_INET;
ifn.lifn_flags = 0;
ifn.lifn_count = 0;
if (ioctl(s, SIOCGLIFNUM, &ifn) < 0) {
close(s);
return -1;
}
bufsz = ifn.lifn_count * sizeof(struct lifreq);
if (!(buf = malloc(bufsz))) {
close(s);
return -1;
}
memset(buf, 0, bufsz);
/* Get a list of interfaces on the machine */
ifc.lifc_len = bufsz;
ifc.lifc_buf = buf;
ifc.lifc_family = AF_INET;
ifc.lifc_flags = 0;
if (ioctl(s, SIOCGLIFCONF, &ifc) < 0) {
close(s);
free(buf);
return -1;
}
for (ifr = ifc.lifc_req, x = 0; x < ifn.lifn_count; ifr++, x++) {
sa = (struct sockaddr_in *)&(ifr->lifr_addr);
score_address(sa, &best_addr, &best_score);
res = 0;
if (best_score == 0)
break;
}
free(buf);
#endif /* SOLARIS */
close(s);
}
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__)
freeifaddrs(ifaphead);
#endif /* BSD_OR_LINUX */
if (res == 0 && ourip)
memcpy(ourip, &best_addr, sizeof(*ourip));
return res;
}
#endif /* HAVE_GETIFADDRS */
/* Free HA structure */
void ast_free_ha(struct ast_ha *ha)
{
struct ast_ha *hal;
while (ha) {
while(ha) {
hal = ha;
ha = ha->next;
free(hal);
@@ -271,12 +112,9 @@ static void ast_copy_ha(struct ast_ha *from, struct ast_ha *to)
/* Create duplicate of ha structure */
static struct ast_ha *ast_duplicate_ha(struct ast_ha *original)
{
struct ast_ha *new_ha;
if ((new_ha = ast_malloc(sizeof(*new_ha)))) {
/* Copy from original to new object */
ast_copy_ha(original, new_ha);
}
struct ast_ha *new_ha = malloc(sizeof(struct ast_ha));
/* Copy from original to new object */
ast_copy_ha(original, new_ha);
return new_ha;
}
@@ -285,16 +123,16 @@ static struct ast_ha *ast_duplicate_ha(struct ast_ha *original)
/* Used in chan_sip2 templates */
struct ast_ha *ast_duplicate_ha_list(struct ast_ha *original)
{
struct ast_ha *start = original;
struct ast_ha *start=original;
struct ast_ha *ret = NULL;
struct ast_ha *link, *prev = NULL;
struct ast_ha *link,*prev=NULL;
while (start) {
link = ast_duplicate_ha(start); /* Create copy of this object */
if (prev)
prev->next = link; /* Link previous to this object */
if (!ret)
if (!ret)
ret = link; /* Save starting point */
start = start->next; /* Go to next object */
@@ -305,20 +143,19 @@ struct ast_ha *ast_duplicate_ha_list(struct ast_ha *original)
struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path)
{
struct ast_ha *ha;
struct ast_ha *ha = malloc(sizeof(struct ast_ha));
char *nm = "255.255.255.255";
char tmp[256];
struct ast_ha *prev = NULL;
struct ast_ha *ret;
int x, z;
unsigned int y;
ret = path;
while (path) {
prev = path;
path = path->next;
}
if ((ha = ast_malloc(sizeof(*ha)))) {
if (ha) {
ast_copy_string(tmp, stuff, sizeof(tmp));
nm = strchr(tmp, '/');
if (!nm) {
@@ -330,7 +167,7 @@ struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path)
if (!strchr(nm, '.')) {
if ((sscanf(nm, "%d", &x) == 1) && (x >= 0) && (x <= 32)) {
y = 0;
for (z = 0; z < x; z++) {
for (z=0;z<x;z++) {
y >>= 1;
y |= 0x80000000;
}
@@ -339,12 +176,12 @@ struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path)
} else if (!inet_aton(nm, &ha->netmask)) {
ast_log(LOG_WARNING, "%s is not a valid netmask\n", nm);
free(ha);
return ret;
return path;
}
if (!inet_aton(tmp, &ha->netaddr)) {
ast_log(LOG_WARNING, "%s is not a valid IP\n", tmp);
free(ha);
return ret;
return path;
}
ha->netaddr.s_addr &= ha->netmask.s_addr;
if (!strncasecmp(sense, "p", 1)) {
@@ -359,8 +196,7 @@ struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path)
ret = ha;
}
}
if (option_debug)
ast_log(LOG_DEBUG, "%s/%s appended to acl for peer\n", stuff, nm);
ast_log(LOG_DEBUG, "%s/%s appended to acl for peer\n", stuff, nm);
return ret;
}
@@ -372,10 +208,10 @@ int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin)
char iabuf[INET_ADDRSTRLEN];
char iabuf2[INET_ADDRSTRLEN];
/* DEBUG */
ast_copy_string(iabuf, ast_inet_ntoa(sin->sin_addr), sizeof(iabuf));
ast_copy_string(iabuf2, ast_inet_ntoa(ha->netaddr), sizeof(iabuf2));
if (option_debug)
ast_log(LOG_DEBUG, "##### Testing %s with %s\n", iabuf, iabuf2);
ast_log(LOG_DEBUG,
"##### Testing %s with %s\n",
ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr),
ast_inet_ntoa(iabuf2, sizeof(iabuf2), ha->netaddr));
/* For each rule, if this address and the netmask = the net address
apply the current rule */
if ((sin->sin_addr.s_addr & ha->netmask.s_addr) == ha->netaddr.s_addr)
@@ -411,55 +247,12 @@ int ast_get_ip_or_srv(struct sockaddr_in *sin, const char *value, const char *se
return 0;
}
struct dscp_codepoint {
char *name;
unsigned int space;
};
/* IANA registered DSCP codepoints */
static const struct dscp_codepoint dscp_pool1[] = {
{ "CS0", 0x00 },
{ "CS1", 0x08 },
{ "CS2", 0x10 },
{ "CS3", 0x18 },
{ "CS4", 0x20 },
{ "CS5", 0x28 },
{ "CS6", 0x30 },
{ "CS7", 0x38 },
{ "AF11", 0x0A },
{ "AF12", 0x0C },
{ "AF13", 0x0E },
{ "AF21", 0x12 },
{ "AF22", 0x14 },
{ "AF23", 0x16 },
{ "AF31", 0x1A },
{ "AF32", 0x1C },
{ "AF33", 0x1E },
{ "AF41", 0x22 },
{ "AF42", 0x24 },
{ "AF43", 0x26 },
{ "EF", 0x2E },
};
int ast_str2tos(const char *value, unsigned int *tos)
int ast_str2tos(const char *value, int *tos)
{
int fval;
unsigned int x;
if (sscanf(value, "%i", &fval) == 1) {
*tos = fval & 0xFF;
return 0;
}
for (x = 0; x < sizeof(dscp_pool1) / sizeof(dscp_pool1[0]); x++) {
if (!strcasecmp(value, dscp_pool1[x].name)) {
*tos = dscp_pool1[x].space << 2;
return 0;
}
}
if (!strcasecmp(value, "lowdelay"))
if (sscanf(value, "%i", &fval) == 1)
*tos = fval & 0xff;
else if (!strcasecmp(value, "lowdelay"))
*tos = IPTOS_LOWDELAY;
else if (!strcasecmp(value, "throughput"))
*tos = IPTOS_THROUGHPUT;
@@ -471,44 +264,16 @@ int ast_str2tos(const char *value, unsigned int *tos)
*tos = 0;
else
return -1;
ast_log(LOG_WARNING, "TOS value %s is deprecated. Please see doc/ip-tos.txt for more information.\n", value);
return 0;
}
const char *ast_tos2str(unsigned int tos)
{
unsigned int x;
switch (tos) {
case 0:
return "none";
case IPTOS_LOWDELAY:
return "lowdelay";
case IPTOS_THROUGHPUT:
return "throughput";
case IPTOS_RELIABILITY:
return "reliability";
case IPTOS_MINCOST:
return "mincost";
default:
for (x = 0; x < sizeof(dscp_pool1) / sizeof(dscp_pool1[0]); x++) {
if (dscp_pool1[x].space == (tos >> 2))
return dscp_pool1[x].name;
}
}
return "unknown";
}
int ast_get_ip(struct sockaddr_in *sin, const char *value)
{
return ast_get_ip_or_srv(sin, value, NULL);
}
/* iface is the interface (e.g. eth0); address is the return value */
int ast_lookup_iface(char *iface, struct in_addr *address)
int ast_lookup_iface(char *iface, struct in_addr *address)
{
int mysock, res = 0;
struct my_ifreq ifreq;
@@ -585,6 +350,6 @@ int ast_find_ourip(struct in_addr *ourip, struct sockaddr_in bindaddr)
/* A.ROOT-SERVERS.NET. */
if (inet_aton("198.41.0.4", &saddr) && !ast_ouraddrfor(&saddr, ourip))
return 0;
return get_local_address(ourip);
return -1;
}

View File

@@ -31,16 +31,12 @@
Issue Date: 26/08/2003
*/
/*! \file
*
* \brief This file contains the code for implementing encryption and decryption
* for AES (Rijndael) for block and key sizes of 16, 24 and 32 bytes. It
* can optionally be replaced by code written in assembler using NASM. For
* further details see the file aesopt.h
*
* \author Dr Brian Gladman <brg@gladman.me.uk>
*/
\brief This file contains the code for implementing encryption and decryption
for AES (Rijndael) for block and key sizes of 16, 24 and 32 bytes. It
can optionally be replaced by code written in assembler using NASM. For
further details see the file aesopt.h
*/
#include "aesopt.h"

View File

@@ -31,15 +31,11 @@
Issue Date: 26/08/2003
*/
/*! \file
*
* \brief This file contains the code for implementing the key schedule for AES
* (Rijndael) for block and key sizes of 16, 24, and 32 bytes. See aesopt.h
* for further details including optimisation.
*
* \author Dr Brian Gladman <brg@gladman.me.uk>
*/
\brief This file contains the code for implementing the key schedule for AES
(Rijndael) for block and key sizes of 16, 24, and 32 bytes. See aesopt.h
for further details including optimisation.
*/
#include "aesopt.h"

View File

@@ -3,7 +3,7 @@
#
# Makefile for AGI-related stuff
#
# Copyright (C) 1999-2006, Digium
# Copyright (C) 1999-2005, Digium
#
# Mark Spencer <markster@digium.com>
#
@@ -11,37 +11,42 @@
# the GNU General Public License
#
.PHONY: clean all uninstall
AGIS=agi-test.agi eagi-test eagi-sphinx-test
AGIS=agi-test.agi eagi-test eagi-sphinx-test jukebox.agi
CFLAGS+=-DNO_AST_MM
LIBS=
ifeq ($(OSARCH),SunOS)
LIBS+=-lsocket -lnsl
LIBS=-lsocket -lnsl ../strcompat.o
endif
include $(ASTTOPDIR)/Makefile.rules
ifeq ($(findstring BSD,${OSARCH}),BSD)
CFLAGS+=-I$(CROSS_COMPILE_TARGET)/usr/local/include -L$(CROSS_COMPILE_TARGET)/usr/local/lib
endif
all: $(AGIS)
strcompat.c: ../main/strcompat.c
@cp $< $@
eagi-test: eagi-test.o strcompat.o
eagi-sphinx-test: eagi-sphinx-test.o
all: depend $(AGIS)
install: all
mkdir -p $(DESTDIR)$(AGI_DIR)
for x in $(AGIS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(AGI_DIR) ; done
uninstall:
for x in $(AGIS); do rm -f $(DESTDIR)$(AGI_DIR)/$$x ; done
eagi-test: eagi-test.o
$(CC) $(CFLAGS) -o eagi-test eagi-test.o $(LIBS)
eagi-sphinx-test: eagi-sphinx-test.o
$(CC) $(CFLAGS) -o eagi-sphinx-test eagi-sphinx-test.o $(LIBS)
clean:
rm -f *.so *.o look eagi-test eagi-sphinx-test
rm -f .*.d *.s *.i
rm -f strcompat.c
rm -f *.so *.o look .depend eagi-test eagi-sphinx-test
ifneq ($(wildcard .*.d),)
include .*.d
%.so : %.o
$(CC) -shared -Xlinker -x -o $@ $<
ifneq ($(wildcard .depend),)
include .depend
endif
depend: .depend
.depend:
../build_tools/mkdep $(CFLAGS) `ls *.c`

View File

@@ -17,10 +17,7 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include "asterisk.h"
#include "asterisk/compat.h"
#include <asterisk/compat.h>
#define AUDIO_FILENO (STDERR_FILENO + 1)
@@ -70,9 +67,7 @@ static int read_environment(void)
char *val;
/* Read environment */
for(;;) {
if (!fgets(buf, sizeof(buf), stdin)) {
return -1;
}
fgets(buf, sizeof(buf), stdin);
if (feof(stdin))
return -1;
buf[strlen(buf) - 1] = '\0';
@@ -123,9 +118,7 @@ static char *wait_result(void)
return NULL;
}
if (FD_ISSET(STDIN_FILENO, &fds)) {
if (!fgets(astresp, sizeof(astresp), stdin)) {
return NULL;
}
fgets(astresp, sizeof(astresp), stdin);
if (feof(stdin)) {
fprintf(stderr, "Got hungup on apparently\n");
return NULL;
@@ -136,10 +129,9 @@ static char *wait_result(void)
}
if (FD_ISSET(AUDIO_FILENO, &fds)) {
res = read(AUDIO_FILENO, audiobuf, sizeof(audiobuf));
if ((res > 0) && (sphinx_sock > -1)) {
if (write(sphinx_sock, audiobuf, res) < 0) {
fprintf(stderr, "write() failed: %s\n", strerror(errno));
}
if (res > 0) {
if (sphinx_sock > -1)
write(sphinx_sock, audiobuf, res);
}
}
if ((sphinx_sock > -1) && FD_ISSET(sphinx_sock, &fds)) {

View File

@@ -11,10 +11,7 @@
#include <errno.h>
#include <string.h>
#include <sys/select.h>
#include "asterisk.h"
#include "asterisk/compat.h"
#include <asterisk/compat.h>
#define AUDIO_FILENO (STDERR_FILENO + 1)
@@ -24,9 +21,7 @@ static int read_environment(void)
char *val;
/* Read environment */
for(;;) {
if (!fgets(buf, sizeof(buf), stdin)) {
return -1;
}
fgets(buf, sizeof(buf), stdin);
if (feof(stdin))
return -1;
buf[strlen(buf) - 1] = '\0';
@@ -70,9 +65,7 @@ static char *wait_result(void)
return NULL;
}
if (FD_ISSET(STDIN_FILENO, &fds)) {
if (!fgets(astresp, sizeof(astresp), stdin)) {
return NULL;
}
fgets(astresp, sizeof(astresp), stdin);
if (feof(stdin)) {
fprintf(stderr, "Got hungup on apparently\n");
return NULL;

View File

@@ -1,488 +0,0 @@
#!/usr/bin/perl
#
# Jukebox 0.2
#
# A music manager for Asterisk.
#
# Copyright (C) 2005-2006, Justin Tunney
#
# Justin Tunney <jesuscyborg@gmail.com>
#
# This program is free software, distributed under the terms of the
# GNU General Public License v2.
#
# Keep it open source pigs
#
# --------------------------------------------------------------------
#
# Uses festival to list off all your MP3 music files over a channel in
# a hierarchical fashion. Put this file in your agi-bin folder which
# is located at: /var/lib/asterisk/agi-bin Be sure to chmod +x it!
#
# Invocation Example:
# exten => 68742,1,Answer()
# exten => 68742,2,agi,jukebox.agi|/home/justin/Music
# exten => 68742,3,Hangup()
#
# exten => 68742,1,Answer()
# exten => 68742,2,agi,jukebox.agi|/home/justin/Music|pm
# exten => 68742,3,Hangup()
#
# Options:
# p - Precache text2wave outputs for every possible filename.
# It is much better to set this option because if a caller
# presses a key during a cache operation, it will be ignored.
# m - Go back to menu after playing song
# g - Do not play the greeting message
#
# Usage Instructions:
# - Press '*' to go up a directory. If you are in the root music
# folder you will be exitted from the script.
# - If you have a really long list of files, you can filter the list
# at any time by pressing '#' and spelling out a few letters you
# expect the files to start with. For example, if you wanted to
# know what extension 'Requiem For A Dream' was, you'd type:
# '#737'. Note, phone keypads don't include Q and Z. Q is 7 and
# Z is 9.
#
# Notes:
# - This AGI script uses the MP3Player command which uses the
# mpg123 Program. Grab yourself a copy of this program by
# going to http://www.mpg123.de/cgi-bin/sitexplorer.cgi?/mpg123/
# Be sure to download mpg123-0.59r.tar.gz because it is known to
# work with Asterisk and hopefully isn't the release with that
# awful security problem. If you're using Fedora Core 3 with
# Alsa like me, make linux-alsa isn't going to work. Do make
# linux-devel and you're peachy keen.
#
# - You won't get nifty STDERR debug messages if you're using a
# remote asterisk shell.
#
# - For some reason, caching certain files will generate the
# error: 'using default diphone ax-ax for y-pau'. Example:
# # echo "Depeche Mode - CUW - 05 - The Meaning of Love" | text2wave -o /var/jukeboxcache/jukeboxcache/Depeche_Mode/Depeche_Mode_-_CUW_-_05_-_The_Meaning_of_Love.mp3.ul -otype ulaw -
# The temporary work around is to just touch these files.
#
# - The background app doesn't like to get more than 2031 chars
# of input.
#
use strict;
$|=1;
# Setup some variables
my %AGI; my $tests = 0; my $fail = 0; my $pass = 0;
my @masterCacheList = ();
my $maxNumber = 10;
while (<STDIN>) {
chomp;
last unless length($_);
if (/^agi_(\w+)\:\s+(.*)$/) {
$AGI{$1} = $2;
}
}
# setup options
my $SHOWGREET = 1;
my $PRECACHE = 0;
my $MENUAFTERSONG = 0;
$PRECACHE = 1 if $ARGV[1] =~ /p/;
$MENUAFTERSONG = 1 if $ARGV[1] =~ /m/;
$SHOWGREET = 0 if $ARGV[1] =~ /g/;
# setup folders
my $MUSIC = $ARGV[0];
$MUSIC = &rmts($MUSIC);
my $FESTIVALCACHE = "/var/jukeboxcache";
if (! -e $FESTIVALCACHE) {
`mkdir -p -m0776 $FESTIVALCACHE`;
}
# make sure we have some essential files
if (! -e "$FESTIVALCACHE/jukebox_greet.ul") {
`echo "Welcome to the Asterisk Jukebox" | text2wave -o $FESTIVALCACHE/jukebox_greet.ul -otype ulaw -`;
}
if (! -e "$FESTIVALCACHE/jukebox_press.ul") {
`echo "Press" | text2wave -o $FESTIVALCACHE/jukebox_press.ul -otype ulaw -`;
}
if (! -e "$FESTIVALCACHE/jukebox_for.ul") {
`echo "For" | text2wave -o $FESTIVALCACHE/jukebox_for.ul -otype ulaw -`;
}
if (! -e "$FESTIVALCACHE/jukebox_toplay.ul") {
`echo "To play" | text2wave -o $FESTIVALCACHE/jukebox_toplay.ul -otype ulaw -`;
}
if (! -e "$FESTIVALCACHE/jukebox_nonefound.ul") {
`echo "There were no music files found in this folder" | text2wave -o $FESTIVALCACHE/jukebox_nonefound.ul -otype ulaw -`;
}
if (! -e "$FESTIVALCACHE/jukebox_percent.ul") {
`echo "Percent" | text2wave -o $FESTIVALCACHE/jukebox_percent.ul -otype ulaw -`;
}
if (! -e "$FESTIVALCACHE/jukebox_generate.ul") {
`echo "Please wait while Astrisk Jukebox cashes the files of your music collection" | text2wave -o $FESTIVALCACHE/jukebox_generate.ul -otype ulaw -`;
}
if (! -e "$FESTIVALCACHE/jukebox_invalid.ul") {
`echo "You have entered an invalid selection" | text2wave -o $FESTIVALCACHE/jukebox_invalid.ul -otype ulaw -`;
}
if (! -e "$FESTIVALCACHE/jukebox_thankyou.ul") {
`echo "Thank you for using Astrisk Jukebox, Goodbye" | text2wave -o $FESTIVALCACHE/jukebox_thankyou.ul -otype ulaw -`;
}
# greet the user
if ($SHOWGREET) {
print "EXEC Playback \"$FESTIVALCACHE/jukebox_greet\"\n";
my $result = <STDIN>; &check_result($result);
}
# go through the directories
music_dir_cache() if $PRECACHE;
music_dir_menu('/');
exit 0;
##########################################################################
sub music_dir_menu {
my $dir = shift;
# generate a list of mp3's and directories and assign each one it's
# own selection number. Then make sure that we've got a sound clip
# for the file name
if (!opendir(THEDIR, rmts($MUSIC.$dir))) {
print STDERR "Failed to open music directory: $dir\n";
exit 1;
}
my @files = sort readdir THEDIR;
my $cnt = 1;
my @masterBgList = ();
foreach my $file (@files) {
chomp($file);
if ($file ne '.' && $file ne '..' && $file ne 'festivalcache') { # ignore special files
my $real_version = &rmts($MUSIC.$dir).'/'.$file;
my $cache_version = &rmts($FESTIVALCACHE.$dir).'/'.$file.'.ul';
my $cache_version2 = &rmts($FESTIVALCACHE.$dir).'/'.$file;
my $cache_version_esc = &clean_file($cache_version);
my $cache_version2_esc = &clean_file($cache_version2);
if (-d $real_version) {
# 0:id 1:type 2:text2wav-file 3:for-filtering 4:the-directory 5:text2wav echo
push(@masterBgList, [$cnt++, 1, $cache_version2_esc, &remove_special_chars($file), $file, "for the $file folder"]);
} elsif ($real_version =~ /\.mp3$/) {
# 0:id 1:type 2:text2wav-file 3:for-filtering 4:the-mp3
push(@masterBgList, [$cnt++, 2, $cache_version2_esc, &remove_special_chars($file), $real_version, "to play $file"]);
}
}
}
close(THEDIR);
my @filterList = @masterBgList;
if (@filterList == 0) {
print "EXEC Playback \"$FESTIVALCACHE/jukebox_nonefound\"\n";
my $result = <STDIN>; &check_result($result);
return 0;
}
for (;;) {
MYCONTINUE:
# play bg selections and figure out their selection
my $digit = '';
my $digitstr = '';
for (my $n=0; $n<@filterList; $n++) {
&cache_speech(&remove_file_extension($filterList[$n][5]), "$filterList[$n][2].ul") if ! -e "$filterList[$n][2].ul";
&cache_speech("Press $filterList[$n][0]", "$FESTIVALCACHE/jukebox_$filterList[$n][0].ul") if ! -e "$FESTIVALCACHE/jukebox_$filterList[$n][0].ul";
print "EXEC Background \"$filterList[$n][2]&$FESTIVALCACHE/jukebox_$filterList[$n][0]\"\n";
my $result = <STDIN>;
$digit = &check_result($result);
if ($digit > 0) {
$digitstr .= chr($digit);
last;
}
}
for (;;) {
print "WAIT FOR DIGIT 3000\n";
my $result = <STDIN>;
$digit = &check_result($result);
last if $digit <= 0;
$digitstr .= chr($digit);
}
# see if it's a valid selection
print STDERR "Digits Entered: '$digitstr'\n";
exit 0 if $digitstr eq '';
my $found = 0;
goto EXITSUB if $digitstr =~ /\*/;
# filter the list
if ($digitstr =~ /^\#\d+/) {
my $regexp = '';
for (my $n=1; $n<length($digitstr); $n++) {
my $d = substr($digitstr, $n, 1);
if ($d == 2) {
$regexp .= '[abc]';
} elsif ($d == 3) {
$regexp .= '[def]';
} elsif ($d == 4) {
$regexp .= '[ghi]';
} elsif ($d == 5) {
$regexp .= '[jkl]';
} elsif ($d == 6) {
$regexp .= '[mno]';
} elsif ($d == 7) {
$regexp .= '[pqrs]';
} elsif ($d == 8) {
$regexp .= '[tuv]';
} elsif ($d == 9) {
$regexp .= '[wxyz]';
}
}
@filterList = ();
for (my $n=1; $n<@masterBgList; $n++) {
push(@filterList, $masterBgList[$n]) if $masterBgList[$n][3] =~ /^$regexp/i;
}
goto MYCONTINUE;
}
for (my $n=0; $n<@masterBgList; $n++) {
if ($digitstr == $masterBgList[$n][0]) {
if ($masterBgList[$n][1] == 1) { # a folder
&music_dir_menu(rmts($dir).'/'.$masterBgList[$n][4]);
@filterList = @masterBgList;
goto MYCONTINUE;
} elsif ($masterBgList[$n][1] == 2) { # a file
# because *'s scripting language is crunk and won't allow us to escape
# funny filenames, we need to create a temporary symlink to the mp3
# file
my $mp3 = &escape_file($masterBgList[$n][4]);
my $link = `mktemp`;
chomp($link);
$link .= '.mp3';
print STDERR "ln -s $mp3 $link\n";
my $cmdr = `ln -s $mp3 $link`;
chomp($cmdr);
print "Failed to create symlink to mp3: $cmdr\n" if $cmdr ne '';
print "EXEC MP3Player \"$link\"\n";
my $result = <STDIN>; &check_result($result);
`rm $link`;
if (!$MENUAFTERSONG) {
print "EXEC Playback \"$FESTIVALCACHE/jukebox_thankyou\"\n";
my $result = <STDIN>; &check_result($result);
exit 0;
} else {
goto MYCONTINUE;
}
}
}
}
print "EXEC Playback \"$FESTIVALCACHE/jukebox_invalid\"\n";
my $result = <STDIN>; &check_result($result);
}
EXITSUB:
}
sub cache_speech {
my $speech = shift;
my $file = shift;
my $theDir = extract_file_dir($file);
`mkdir -p -m0776 $theDir`;
print STDERR "echo \"$speech\" | text2wave -o $file -otype ulaw -\n";
my $cmdr = `echo "$speech" | text2wave -o $file -otype ulaw -`;
chomp($cmdr);
if ($cmdr =~ /using default diphone/) {
# temporary bug work around....
`touch $file`;
} elsif ($cmdr ne '') {
print STDERR "Command Failed\n";
exit 1;
}
}
sub music_dir_cache {
# generate list of text2speech files to generate
if (!music_dir_cache_genlist('/')) {
print STDERR "Horrible Dreadful Error: No Music Found in $MUSIC!";
exit 1;
}
# add to list how many 'number' files we have to generate. We can't
# use the SayNumber app in Asterisk because we want to chain all
# talking in one Background command. We also want a consistent
# voice...
for (my $n=1; $n<=$maxNumber; $n++) {
push(@masterCacheList, [3, "Press $n", "$FESTIVALCACHE/jukebox_$n.ul"]) if ! -e "$FESTIVALCACHE/jukebox_$n.ul";
}
# now generate all these darn text2speech files
if (@masterCacheList > 5) {
print "EXEC Playback \"$FESTIVALCACHE/jukebox_generate\"\n";
my $result = <STDIN>; &check_result($result);
}
my $theTime = time();
for (my $n=0; $n < @masterCacheList; $n++) {
my $cmdr = '';
if ($masterCacheList[$n][0] == 1) { # directory
&cache_speech("for folder $masterCacheList[$n][1]", $masterCacheList[$n][2]);
} elsif ($masterCacheList[$n][0] == 2) { # file
&cache_speech("to play $masterCacheList[$n][1]", $masterCacheList[$n][2]);
} elsif ($masterCacheList[$n][0] == 3) { # number
&cache_speech($masterCacheList[$n][1], $masterCacheList[$n][2]);
}
if (time() >= $theTime + 30) {
my $percent = int($n / @masterCacheList * 100);
print "SAY NUMBER $percent \"\"\n";
my $result = <STDIN>; &check_result($result);
print "EXEC Playback \"$FESTIVALCACHE/jukebox_percent\"\n";
my $result = <STDIN>; &check_result($result);
$theTime = time();
}
}
}
# this function will fill the @masterCacheList of all the files that
# need to have text2speeced ulaw files of their names generated
sub music_dir_cache_genlist {
my $dir = shift;
if (!opendir(THEDIR, rmts($MUSIC.$dir))) {
print STDERR "Failed to open music directory: $dir\n";
exit 1;
}
my @files = sort readdir THEDIR;
my $foundFiles = 0;
my $tmpMaxNum = 0;
foreach my $file (@files) {
chomp;
if ($file ne '.' && $file ne '..' && $file ne 'festivalcache') { # ignore special files
my $real_version = &rmts($MUSIC.$dir).'/'.$file;
my $cache_version = &rmts($FESTIVALCACHE.$dir).'/'.$file.'.ul';
my $cache_version2 = &rmts($FESTIVALCACHE.$dir).'/'.$file;
my $cache_version_esc = &clean_file($cache_version);
my $cache_version2_esc = &clean_file($cache_version2);
if (-d $real_version) {
if (music_dir_cache_genlist(rmts($dir).'/'.$file)) {
$tmpMaxNum++;
$maxNumber = $tmpMaxNum if $tmpMaxNum > $maxNumber;
push(@masterCacheList, [1, $file, $cache_version_esc]) if ! -e $cache_version_esc;
$foundFiles = 1;
}
} elsif ($real_version =~ /\.mp3$/) {
$tmpMaxNum++;
$maxNumber = $tmpMaxNum if $tmpMaxNum > $maxNumber;
push(@masterCacheList, [2, &remove_file_extension($file), $cache_version_esc]) if ! -e $cache_version_esc;
$foundFiles = 1;
}
}
}
close(THEDIR);
return $foundFiles;
}
sub rmts { # remove trailing slash
my $hog = shift;
$hog =~ s/\/$//;
return $hog;
}
sub extract_file_name {
my $hog = shift;
$hog =~ /\/?([^\/]+)$/;
return $1;
}
sub extract_file_dir {
my $hog = shift;
return $hog if ! ($hog =~ /\//);
$hog =~ /(.*)\/[^\/]*$/;
return $1;
}
sub remove_file_extension {
my $hog = shift;
return $hog if ! ($hog =~ /\./);
$hog =~ /(.*)\.[^.]*$/;
return $1;
}
sub clean_file {
my $hog = shift;
$hog =~ s/\\/_/g;
$hog =~ s/ /_/g;
$hog =~ s/\t/_/g;
$hog =~ s/\'/_/g;
$hog =~ s/\"/_/g;
$hog =~ s/\(/_/g;
$hog =~ s/\)/_/g;
$hog =~ s/&/_/g;
$hog =~ s/\[/_/g;
$hog =~ s/\]/_/g;
$hog =~ s/\$/_/g;
$hog =~ s/\|/_/g;
$hog =~ s/\^/_/g;
return $hog;
}
sub remove_special_chars {
my $hog = shift;
$hog =~ s/\\//g;
$hog =~ s/ //g;
$hog =~ s/\t//g;
$hog =~ s/\'//g;
$hog =~ s/\"//g;
$hog =~ s/\(//g;
$hog =~ s/\)//g;
$hog =~ s/&//g;
$hog =~ s/\[//g;
$hog =~ s/\]//g;
$hog =~ s/\$//g;
$hog =~ s/\|//g;
$hog =~ s/\^//g;
return $hog;
}
sub escape_file {
my $hog = shift;
$hog =~ s/\\/\\\\/g;
$hog =~ s/ /\\ /g;
$hog =~ s/\t/\\\t/g;
$hog =~ s/\'/\\\'/g;
$hog =~ s/\"/\\\"/g;
$hog =~ s/\(/\\\(/g;
$hog =~ s/\)/\\\)/g;
$hog =~ s/&/\\&/g;
$hog =~ s/\[/\\\[/g;
$hog =~ s/\]/\\\]/g;
$hog =~ s/\$/\\\$/g;
$hog =~ s/\|/\\\|/g;
$hog =~ s/\^/\\\^/g;
return $hog;
}
sub check_result {
my ($res) = @_;
my $retval;
$tests++;
chomp $res;
if ($res =~ /^200/) {
$res =~ /result=(-?\d+)/;
if (!length($1)) {
print STDERR "FAIL ($res)\n";
$fail++;
exit 1;
} else {
print STDERR "PASS ($1)\n";
return $1;
}
} else {
print STDERR "FAIL (unexpected result '$res')\n";
exit 1;
}
}

View File

@@ -19,8 +19,7 @@
/*! \file
*
* \brief u-Law to Signed linear conversion
*
* \author Mark Spencer <markster@digium.com>
*
*/
#include "asterisk.h"
@@ -71,7 +70,7 @@ static inline short int alaw2linear (unsigned char alaw)
int seg;
alaw ^= AMI_MASK;
i = ((alaw & 0x0F) << 4) + 8 /* rounding error */;
i = ((alaw & 0x0F) << 4);
seg = (((int) alaw & 0x70) >> 4);
if (seg)
i = (i + 0x100) << (seg - 1);

File diff suppressed because it is too large Load Diff

View File

@@ -3,40 +3,131 @@
#
# Makefile for PBX applications
#
# Copyright (C) 1999-2006, Digium, Inc.
# Copyright (C) 1999-2005, Digium
#
# Mark Spencer <markster@digium.com>
#
# This program is free software, distributed under the terms of
# the GNU General Public License
#
-include ../menuselect.makeopts ../menuselect.makedeps
APPS=app_dial.so app_playback.so app_voicemail.so app_directory.so app_mp3.so\
app_system.so app_echo.so app_record.so app_image.so app_url.so app_disa.so \
app_adsiprog.so app_getcpeid.so app_milliwatt.so \
app_zapateller.so app_setcallerid.so app_festival.so \
app_queue.so app_senddtmf.so app_parkandannounce.so \
app_setcidname.so app_lookupcidname.so app_macro.so \
app_authenticate.so app_softhangup.so app_lookupblacklist.so \
app_waitforring.so app_privacy.so app_db.so app_chanisavail.so \
app_enumlookup.so app_transfer.so app_setcidnum.so app_cdr.so \
app_hasnewvoicemail.so app_sayunixtime.so app_cut.so app_read.so \
app_setcdruserfield.so app_random.so app_ices.so app_eval.so \
app_nbscat.so app_sendtext.so app_exec.so \
app_groupcount.so app_txtcidname.so app_controlplayback.so \
app_talkdetect.so app_alarmreceiver.so app_userevent.so app_verbose.so \
app_test.so app_forkcdr.so app_math.so app_realtime.so \
app_dumpchan.so app_waitforsilence.so app_while.so app_setrdnis.so \
app_md5.so app_readfile.so app_chanspy.so app_settransfercapability.so \
app_dictate.so app_externalivr.so app_directed_pickup.so \
app_mixmonitor.so app_stack.so
MENUSELECT_CATEGORY=APPS
MENUSELECT_DESCRIPTION=Applications
#
# Obsolete things...
#
#APPS+=app_sql_postgres.so
#APPS+=app_sql_odbc.so
ALL_C_MODS:=$(patsubst %.c,%,$(wildcard app_*.c))
ALL_CC_MODS:=$(patsubst %.cc,%,$(wildcard app_*.cc))
#
# Experimental things
#
#APPS+=app_ivrdemo.so
#APPS+=app_skel.so
#APPS+=app_rpt.so
C_MODS:=$(filter-out $(MENUSELECT_APPS),$(ALL_C_MODS))
CC_MODS:=$(filter-out $(MENUSELECT_APPS),$(ALL_CC_MODS))
ifndef WITHOUT_ZAPTEL
ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/linux/zaptel.h)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/zaptel.h),)
APPS+=app_zapras.so app_meetme.so app_flash.so app_zapbarge.so app_zapscan.so app_page.so
endif
endif # WITHOUT_ZAPTEL
LOADABLE_MODS:=$(C_MODS) $(CC_MODS)
ifneq ($(findstring apps,$(MENUSELECT_EMBED)),)
EMBEDDED_MODS:=$(LOADABLE_MODS)
LOADABLE_MODS:=
ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/osp/osp.h $(CROSS_COMPILE_TARGET)/usr/include/osp/osp.h),)
APPS+=app_osplookup.so
endif
MENUSELECT_OPTS_app_directory:=$(MENUSELECT_OPTS_app_voicemail)
ifneq ($(findstring ODBC_STORAGE,$(MENUSELECT_OPTS_app_voicemail)),)
MENUSELECT_DEPENDS_app_voicemail+=$(MENUSELECT_DEPENDS_ODBC_STORAGE)
MENUSELECT_DEPENDS_app_directory+=$(MENUSELECT_DEPENDS_ODBC_STORAGE)
endif
ifneq ($(findstring IMAP_STORAGE,$(MENUSELECT_OPTS_app_voicemail)),)
MENUSELECT_DEPENDS_app_voicemail+=$(MENUSELECT_DEPENDS_IMAP_STORAGE)
MENUSELECT_DEPENDS_app_directory+=$(MENUSELECT_DEPENDS_IMAP_STORAGE)
ifeq ($(findstring BSD,${OSARCH}),BSD)
CFLAGS+=-I$(CROSS_COMPILE_TARGET)/usr/local/include -L$(CROSS_COMPILE_TARGET)/usr/local/lib
endif
all: _all
CURLLIBS=$(shell $(CROSS_COMPILE_BIN)curl-config --libs)
ifneq ($(shell if [[ 0x`$(CROSS_COMPILE_BIN)curl-config --vernum` -ge 0x70907 ]]; then echo "OK" ; fi),)
ifneq (${CURLLIBS},)
APPS+=app_curl.so
endif
endif
include $(ASTTOPDIR)/Makefile.moddir_rules
ifeq (${OSARCH},CYGWIN)
CYGSOLINK=-Wl,--out-implib=lib$@.a -Wl,--export-all-symbols
CYGSOLIB=-L.. -L. -L../res -lasterisk.dll -lres_features.so -lres_adsi.so -lres_monitor.so
else
CFLAGS+=-fPIC
APPS+=app_sms.so
endif
#
# If you have UnixODBC you can use ODBC voicemail
# storage
#
# Uncomment to use ODBC storage
#CFLAGS+=-DUSE_ODBC_STORAGE
# Uncomment for extended ODBC voicemail storage
#CFLAGS+=-DEXTENDED_ODBC_STORAGE
# See doc/README.odbcstorage for more information
all: $(APPS)
clean:
rm -f *.so *.o look .depend
%.so : %.o
$(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB}
app_rpt.so : app_rpt.o
$(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB} -ltonezone
install: all
for x in $(APPS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(MODULES_DIR) ; done
rm -f $(DESTDIR)$(MODULES_DIR)/app_datetime.so
rm -f $(DESTDIR)$(MODULES_DIR)/app_qcall.so
app_curl.so: app_curl.o
$(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB} $(CURLLIBS)
app_sql_postgres.o: app_sql_postgres.c
$(CC) -pipe -I$(CROSS_COMPILE_TARGET)/usr/local/pgsql/include -I$(CROSS_COMPILE_TARGET)/usr/include/postgresql $(CFLAGS) -c -o app_sql_postgres.o app_sql_postgres.c
app_sql_postgres.so: app_sql_postgres.o
$(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB} -L/usr/local/pgsql/lib -lpq
app_sql_odbc.so: app_sql_odbc.o
$(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB} -lodbc
look: look.c
$(CC) -pipe -O6 -g look.c -o look -lncurses
ifeq (SunOS,$(shell uname))
app_chanspy.so: app_chanspy.o
$(CC) $(SOLINK) -o $@ $< -lrt
endif
ifneq ($(wildcard .depend),)
include .depend
endif
depend: .depend
.depend:
../build_tools/mkdep $(CFLAGS) `ls *.c`
env:
env

View File

@@ -17,22 +17,11 @@
*/
/*! \file
*
* \brief Program Asterisk ADSI Scripts into phone
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
/*** MODULEINFO
<depend>res_adsi</depend>
***/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <sys/types.h>
#include <netinet/in.h>
#include <stdlib.h>
@@ -43,6 +32,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdio.h>
#include <errno.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
@@ -53,6 +46,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/utils.h"
#include "asterisk/lock.h"
static char *tdesc = "Asterisk ADSI Programming Application";
static char *app = "ADSIProg";
static char *synopsis = "Load Asterisk ADSI Scripts into phone";
@@ -63,6 +58,10 @@ static char *descrip =
" ADSIProg(script): This application programs an ADSI Phone with the given\n"
"script. If nothing is specified, the default script (asterisk.adsi) is used.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
struct adsi_event {
int id;
char *name;
@@ -1357,16 +1356,17 @@ static struct adsi_script *compile_script(char *script)
ast_log(LOG_WARNING, "Can't open file '%s'\n", fn);
return NULL;
}
if (!(scr = ast_calloc(1, sizeof(*scr)))) {
scr = malloc(sizeof(struct adsi_script));
if (!scr) {
fclose(f);
ast_log(LOG_WARNING, "Out of memory loading script '%s'\n", fn);
return NULL;
}
memset(scr, 0, sizeof(struct adsi_script));
/* Create "main" as first subroutine */
getsubbyname(scr, "main", NULL, 0);
while(!feof(f)) {
if (!fgets(buf, sizeof(buf), f)) {
continue;
}
fgets(buf, sizeof(buf), f);
if (!feof(f)) {
lineno++;
/* Trim off trailing return */
@@ -1444,11 +1444,11 @@ static int adsi_prog(struct ast_channel *chan, char *script)
return -1;
/* Start an empty ADSI Session */
if (ast_adsi_load_session(chan, NULL, 0, 1) < 1)
if (adsi_load_session(chan, NULL, 0, 1) < 1)
return -1;
/* Now begin the download attempt */
if (ast_adsi_begin_download(chan, scr->desc, scr->fdn, scr->sec, scr->ver)) {
if (adsi_begin_download(chan, scr->desc, scr->fdn, scr->sec, scr->ver)) {
/* User rejected us for some reason */
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "User rejected download attempt\n");
@@ -1462,7 +1462,7 @@ static int adsi_prog(struct ast_channel *chan, char *script)
for (x=0;x<scr->numkeys;x++) {
if (bytes + scr->keys[x].retstrlen > 253) {
/* Send what we've collected so far */
if (ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
if (adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
return -1;
}
@@ -1475,7 +1475,7 @@ static int adsi_prog(struct ast_channel *chan, char *script)
#endif
}
if (bytes) {
if (ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
if (adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
return -1;
}
@@ -1486,7 +1486,7 @@ static int adsi_prog(struct ast_channel *chan, char *script)
for (x=0;x<scr->numdisplays;x++) {
if (bytes + scr->displays[x].datalen > 253) {
/* Send what we've collected so far */
if (ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
if (adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
return -1;
}
@@ -1499,7 +1499,7 @@ static int adsi_prog(struct ast_channel *chan, char *script)
#endif
}
if (bytes) {
if (ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
if (adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
return -1;
}
@@ -1510,7 +1510,7 @@ static int adsi_prog(struct ast_channel *chan, char *script)
for (x=0;x<scr->numsubs;x++) {
if (bytes + scr->subs[x].datalen > 253) {
/* Send what we've collected so far */
if (ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
if (adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
return -1;
}
@@ -1523,7 +1523,7 @@ static int adsi_prog(struct ast_channel *chan, char *script)
#endif
}
if (bytes) {
if (ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
if (adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
return -1;
}
@@ -1531,11 +1531,11 @@ static int adsi_prog(struct ast_channel *chan, char *script)
bytes = 0;
bytes += ast_adsi_display(buf, ADSI_INFO_PAGE, 1, ADSI_JUST_LEFT, 0, "Download complete.", "");
bytes += ast_adsi_set_line(buf, ADSI_INFO_PAGE, 1);
if (ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY) < 0)
bytes += adsi_display(buf, ADSI_INFO_PAGE, 1, ADSI_JUST_LEFT, 0, "Download complete.", "");
bytes += adsi_set_line(buf, ADSI_INFO_PAGE, 1);
if (adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY) < 0)
return -1;
if (ast_adsi_end_download(chan)) {
if (adsi_end_download(chan)) {
/* Download failed for some reason */
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Download attempt failed\n");
@@ -1544,21 +1544,21 @@ static int adsi_prog(struct ast_channel *chan, char *script)
return -1;
}
free(scr);
ast_adsi_unload_session(chan);
adsi_unload_session(chan);
return 0;
}
static int adsi_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct ast_module_user *u;
struct localuser *u;
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
if (ast_strlen_zero(data))
data = "asterisk.adsi";
if (!ast_adsi_available(chan)) {
if (!adsi_available(chan)) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "ADSI Unavailable on CPE. Not bothering to try.\n");
} else {
@@ -1567,26 +1567,40 @@ static int adsi_exec(struct ast_channel *chan, void *data)
res = adsi_prog(chan, data);
}
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
ast_module_user_hangup_all();
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, adsi_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Asterisk ADSI Programming Application");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -22,17 +22,13 @@
*
* *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***
*
* Use at your own risk. Please consult the GNU GPL license document included with Asterisk. *
* Use at your own risk. Please consult the GNU GPL license document included with Asterisk details. *
*
* *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
@@ -41,6 +37,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <unistd.h>
#include <sys/time.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
@@ -56,7 +56,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/localtime.h"
#include "asterisk/callerid.h"
#include "asterisk/astdb.h"
#include "asterisk/utils.h"
#define ALMRCV_CONFIG "alarmreceiver.conf"
#define ADEMCO_CONTACT_ID "ADEMCO_CONTACT_ID"
@@ -68,9 +67,11 @@ struct event_node{
typedef struct event_node event_node_t;
static char *tdesc = "Alarm Receiver for Asterisk";
static char *app = "AlarmReceiver";
static char *synopsis = "Provide support for receiving alarm reports from a burglar or fire alarm panel";
static char *synopsis = "Provide support for receving alarm reports from a burglar or fire alarm panel";
static char *descrip =
" AlarmReceiver(): Only 1 signalling format is supported at this time: Ademco\n"
"Contact ID. This application should be called whenever there is an alarm\n"
@@ -93,10 +94,18 @@ static char event_app[128] = {'\0'};
static char db_family[128] = {'\0'};
static char time_stamp_format[128] = {"%a %b %d, %Y @ %H:%M:%S %Z"};
/* Misc variables */
static char event_file[14] = "/event-XXXXXX";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
/*
* Attempt to access a database variable and increment it,
* provided that the user defined db-family in alarmreceiver.conf
@@ -136,7 +145,7 @@ static void database_increment( char *key )
res = ast_db_put(db_family, key, value);
if((res)&&(option_verbose >= 4))
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: database_increment write error\n");
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: database_increment write error");
return;
}
@@ -206,7 +215,6 @@ static int send_tone_burst(struct ast_channel *chan, float freq, int duration, i
i += wf.datalen / 8;
if (i > duration) {
ast_frfree(f);
break;
}
if (ast_write(chan, &wf)){
@@ -214,7 +222,6 @@ static int send_tone_burst(struct ast_channel *chan, float freq, int duration, i
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Failed to write frame on %s\n", chan->name);
ast_log(LOG_WARNING, "AlarmReceiver Failed to write frame on %s\n",chan->name);
res = -1;
ast_frfree(f);
break;
}
}
@@ -549,9 +556,9 @@ static int receive_ademco_contact_id( struct ast_channel *chan, void *data, int
checksum = checksum % 15;
if (checksum) {
if(checksum){
database_increment("checksum-errors");
if (option_verbose >= 2)
if(option_verbose >= 2)
ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Nonzero checksum\n");
ast_log(LOG_DEBUG, "AlarmReceiver: Nonzero checksum\n");
continue;
@@ -571,11 +578,17 @@ static int receive_ademco_contact_id( struct ast_channel *chan, void *data, int
events_received++;
/* Queue the Event */
if (!(enew = ast_calloc(1, sizeof(*enew)))) {
/* Queue the Event */
if((enew = malloc(sizeof(event_node_t))) == NULL){
if(option_verbose >= 1)
ast_verbose(VERBOSE_PREFIX_1 "AlarmReceiver: Failed to allocate memory\n");
ast_log(LOG_WARNING, "AlarmReceiver Failed to allocate memory\n");
res = -1;
break;
break;
}
memset(enew, 0, sizeof(event_node_t));
enew->next = NULL;
ast_copy_string(enew->data, event, sizeof(enew->data));
@@ -626,13 +639,13 @@ static int receive_ademco_contact_id( struct ast_channel *chan, void *data, int
static int alarmreceiver_exec(struct ast_channel *chan, void *data)
{
int res = 0;
struct ast_module_user *u;
struct localuser *u;
event_node_t *elp, *efree;
char signalling_type[64] = "";
event_node_t *event_head = NULL;
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
/* Set write and read formats to ULAW */
@@ -641,13 +654,13 @@ static int alarmreceiver_exec(struct ast_channel *chan, void *data)
if (ast_set_write_format(chan,AST_FORMAT_ULAW)){
ast_log(LOG_WARNING, "AlarmReceiver: Unable to set write format to Mu-law on %s\n",chan->name);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
if (ast_set_read_format(chan,AST_FORMAT_ULAW)){
ast_log(LOG_WARNING, "AlarmReceiver: Unable to set read format to Mu-law on %s\n",chan->name);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
@@ -666,7 +679,7 @@ static int alarmreceiver_exec(struct ast_channel *chan, void *data)
res = ast_answer(chan);
if (res) {
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
}
@@ -721,7 +734,7 @@ static int alarmreceiver_exec(struct ast_channel *chan, void *data)
}
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return 0;
}
@@ -733,7 +746,7 @@ static int alarmreceiver_exec(struct ast_channel *chan, void *data)
static int load_config(void)
{
struct ast_config *cfg;
const char *p;
char *p;
/* Read in the config file */
@@ -743,7 +756,6 @@ static int load_config(void)
if(option_verbose >= 4)
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: No config file\n");
return 0;
}
else{
@@ -810,7 +822,7 @@ static int load_config(void)
}
ast_config_destroy(cfg);
}
return 1;
return 0;
}
@@ -819,23 +831,36 @@ static int load_config(void)
*/
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
if(load_config())
return ast_register_application(app, alarmreceiver_exec, synopsis, descrip);
else
return AST_MODULE_LOAD_DECLINE;
load_config();
return ast_register_application(app, alarmreceiver_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Alarm Receiver for Asterisk");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,430 +0,0 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2003 - 2006, Aheeva Technology.
*
* Claude Klimos (claude.klimos@aheeva.com)
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*
* A license has been granted to Digium (via disclaimer) for the use of
* this code.
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdio.h>
#include <stdlib.h>
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/dsp.h"
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/app.h"
static char *app = "AMD";
static char *synopsis = "Attempts to detect answering machines";
static char *descrip =
" AMD([initialSilence][|greeting][|afterGreetingSilence][|totalAnalysisTime]\n"
" [|minimumWordLength][|betweenWordsSilence][|maximumNumberOfWords]\n"
" [|silenceThreshold])\n"
" This application attempts to detect answering machines at the beginning\n"
" of outbound calls. Simply call this application after the call\n"
" has been answered (outbound only, of course).\n"
" When loaded, AMD reads amd.conf and uses the parameters specified as\n"
" default values. Those default values get overwritten when calling AMD\n"
" with parameters.\n"
"- 'initialSilence' is the maximum silence duration before the greeting. If\n"
" exceeded then MACHINE.\n"
"- 'greeting' is the maximum length of a greeting. If exceeded then MACHINE.\n"
"- 'afterGreetingSilence' is the silence after detecting a greeting.\n"
" If exceeded then HUMAN.\n"
"- 'totalAnalysisTime' is the maximum time allowed for the algorithm to decide\n"
" on a HUMAN or MACHINE.\n"
"- 'minimumWordLength'is the minimum duration of Voice to considered as a word.\n"
"- 'betweenWordsSilence' is the minimum duration of silence after a word to \n"
" consider the audio that follows as a new word.\n"
"- 'maximumNumberOfWords'is the maximum number of words in the greeting. \n"
" If exceeded then MACHINE.\n"
"- 'silenceThreshold' is the silence threshold.\n"
"This application sets the following channel variable upon completion:\n"
" AMDSTATUS - This is the status of the answering machine detection.\n"
" Possible values are:\n"
" MACHINE | HUMAN | NOTSURE | HANGUP\n"
" AMDCAUSE - Indicates the cause that led to the conclusion.\n"
" Possible values are:\n"
" TOOLONG-<%d total_time>\n"
" INITIALSILENCE-<%d silenceDuration>-<%d initialSilence>\n"
" HUMAN-<%d silenceDuration>-<%d afterGreetingSilence>\n"
" MAXWORDS-<%d wordsCount>-<%d maximumNumberOfWords>\n"
" LONGGREETING-<%d voiceDuration>-<%d greeting>\n";
#define STATE_IN_WORD 1
#define STATE_IN_SILENCE 2
/* Some default values for the algorithm parameters. These defaults will be overwritten from amd.conf */
static int dfltInitialSilence = 2500;
static int dfltGreeting = 1500;
static int dfltAfterGreetingSilence = 800;
static int dfltTotalAnalysisTime = 5000;
static int dfltMinimumWordLength = 100;
static int dfltBetweenWordsSilence = 50;
static int dfltMaximumNumberOfWords = 3;
static int dfltSilenceThreshold = 256;
/* Set to the lowest ms value provided in amd.conf or application parameters */
static int dfltMaxWaitTimeForFrame = 50;
static void isAnsweringMachine(struct ast_channel *chan, void *data)
{
int res = 0;
struct ast_frame *f = NULL;
struct ast_dsp *silenceDetector = NULL;
int dspsilence = 0, readFormat, framelength = 0;
int inInitialSilence = 1;
int inGreeting = 0;
int voiceDuration = 0;
int silenceDuration = 0;
int iTotalTime = 0;
int iWordsCount = 0;
int currentState = STATE_IN_WORD;
int previousState = STATE_IN_SILENCE;
int consecutiveVoiceDuration = 0;
char amdCause[256] = "", amdStatus[256] = "";
char *parse = ast_strdupa(data);
/* Lets set the initial values of the variables that will control the algorithm.
The initial values are the default ones. If they are passed as arguments
when invoking the application, then the default values will be overwritten
by the ones passed as parameters. */
int initialSilence = dfltInitialSilence;
int greeting = dfltGreeting;
int afterGreetingSilence = dfltAfterGreetingSilence;
int totalAnalysisTime = dfltTotalAnalysisTime;
int minimumWordLength = dfltMinimumWordLength;
int betweenWordsSilence = dfltBetweenWordsSilence;
int maximumNumberOfWords = dfltMaximumNumberOfWords;
int silenceThreshold = dfltSilenceThreshold;
int maxWaitTimeForFrame = dfltMaxWaitTimeForFrame;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(argInitialSilence);
AST_APP_ARG(argGreeting);
AST_APP_ARG(argAfterGreetingSilence);
AST_APP_ARG(argTotalAnalysisTime);
AST_APP_ARG(argMinimumWordLength);
AST_APP_ARG(argBetweenWordsSilence);
AST_APP_ARG(argMaximumNumberOfWords);
AST_APP_ARG(argSilenceThreshold);
);
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "AMD: %s %s %s (Fmt: %d)\n", chan->name ,chan->cid.cid_ani, chan->cid.cid_rdnis, chan->readformat);
/* Lets parse the arguments. */
if (!ast_strlen_zero(parse)) {
/* Some arguments have been passed. Lets parse them and overwrite the defaults. */
AST_STANDARD_APP_ARGS(args, parse);
if (!ast_strlen_zero(args.argInitialSilence))
initialSilence = atoi(args.argInitialSilence);
if (!ast_strlen_zero(args.argGreeting))
greeting = atoi(args.argGreeting);
if (!ast_strlen_zero(args.argAfterGreetingSilence))
afterGreetingSilence = atoi(args.argAfterGreetingSilence);
if (!ast_strlen_zero(args.argTotalAnalysisTime))
totalAnalysisTime = atoi(args.argTotalAnalysisTime);
if (!ast_strlen_zero(args.argMinimumWordLength))
minimumWordLength = atoi(args.argMinimumWordLength);
if (!ast_strlen_zero(args.argBetweenWordsSilence))
betweenWordsSilence = atoi(args.argBetweenWordsSilence);
if (!ast_strlen_zero(args.argMaximumNumberOfWords))
maximumNumberOfWords = atoi(args.argMaximumNumberOfWords);
if (!ast_strlen_zero(args.argSilenceThreshold))
silenceThreshold = atoi(args.argSilenceThreshold);
} else if (option_debug)
ast_log(LOG_DEBUG, "AMD using the default parameters.\n");
/* Find lowest ms value, that will be max wait time for a frame */
if (maxWaitTimeForFrame > initialSilence)
maxWaitTimeForFrame = initialSilence;
if (maxWaitTimeForFrame > greeting)
maxWaitTimeForFrame = greeting;
if (maxWaitTimeForFrame > afterGreetingSilence)
maxWaitTimeForFrame = afterGreetingSilence;
if (maxWaitTimeForFrame > totalAnalysisTime)
maxWaitTimeForFrame = totalAnalysisTime;
if (maxWaitTimeForFrame > minimumWordLength)
maxWaitTimeForFrame = minimumWordLength;
if (maxWaitTimeForFrame > betweenWordsSilence)
maxWaitTimeForFrame = betweenWordsSilence;
/* Now we're ready to roll! */
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "AMD: initialSilence [%d] greeting [%d] afterGreetingSilence [%d] "
"totalAnalysisTime [%d] minimumWordLength [%d] betweenWordsSilence [%d] maximumNumberOfWords [%d] silenceThreshold [%d] \n",
initialSilence, greeting, afterGreetingSilence, totalAnalysisTime,
minimumWordLength, betweenWordsSilence, maximumNumberOfWords, silenceThreshold );
/* Set read format to signed linear so we get signed linear frames in */
readFormat = chan->readformat;
if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0 ) {
ast_log(LOG_WARNING, "AMD: Channel [%s]. Unable to set to linear mode, giving up\n", chan->name );
pbx_builtin_setvar_helper(chan , "AMDSTATUS", "");
pbx_builtin_setvar_helper(chan , "AMDCAUSE", "");
return;
}
/* Create a new DSP that will detect the silence */
if (!(silenceDetector = ast_dsp_new())) {
ast_log(LOG_WARNING, "AMD: Channel [%s]. Unable to create silence detector :(\n", chan->name );
pbx_builtin_setvar_helper(chan , "AMDSTATUS", "");
pbx_builtin_setvar_helper(chan , "AMDCAUSE", "");
return;
}
/* Set silence threshold to specified value */
ast_dsp_set_threshold(silenceDetector, silenceThreshold);
/* Now we go into a loop waiting for frames from the channel */
while ((res = ast_waitfor(chan, 2 * maxWaitTimeForFrame)) > -1) {
/* If we fail to read in a frame, that means they hung up */
if (!(f = ast_read(chan))) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "AMD: HANGUP\n");
if (option_debug)
ast_log(LOG_DEBUG, "Got hangup\n");
strcpy(amdStatus, "HANGUP");
break;
}
if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_NULL || f->frametype == AST_FRAME_CNG) {
/* If the total time exceeds the analysis time then give up as we are not too sure */
if (f->frametype == AST_FRAME_VOICE)
framelength = (ast_codec_get_samples(f) / DEFAULT_SAMPLES_PER_MS);
else
framelength += 2 * maxWaitTimeForFrame;
iTotalTime += framelength;
if (iTotalTime >= totalAnalysisTime) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "AMD: Channel [%s]. Too long...\n", chan->name );
ast_frfree(f);
strcpy(amdStatus , "NOTSURE");
sprintf(amdCause , "TOOLONG-%d", iTotalTime);
break;
}
/* Feed the frame of audio into the silence detector and see if we get a result */
if (f->frametype != AST_FRAME_VOICE)
dspsilence += 2 * maxWaitTimeForFrame;
else {
dspsilence = 0;
ast_dsp_silence(silenceDetector, f, &dspsilence);
}
if (dspsilence > 0) {
silenceDuration = dspsilence;
if (silenceDuration >= betweenWordsSilence) {
if (currentState != STATE_IN_SILENCE ) {
previousState = currentState;
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "AMD: Changed state to STATE_IN_SILENCE\n");
}
currentState = STATE_IN_SILENCE;
consecutiveVoiceDuration = 0;
}
if (inInitialSilence == 1 && silenceDuration >= initialSilence) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "AMD: ANSWERING MACHINE: silenceDuration:%d initialSilence:%d\n",
silenceDuration, initialSilence);
ast_frfree(f);
strcpy(amdStatus , "MACHINE");
sprintf(amdCause , "INITIALSILENCE-%d-%d", silenceDuration, initialSilence);
res = 1;
break;
}
if (silenceDuration >= afterGreetingSilence && inGreeting == 1) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "AMD: HUMAN: silenceDuration:%d afterGreetingSilence:%d\n",
silenceDuration, afterGreetingSilence);
ast_frfree(f);
strcpy(amdStatus , "HUMAN");
sprintf(amdCause , "HUMAN-%d-%d", silenceDuration, afterGreetingSilence);
res = 1;
break;
}
} else {
consecutiveVoiceDuration += framelength;
voiceDuration += framelength;
/* If I have enough consecutive voice to say that I am in a Word, I can only increment the
number of words if my previous state was Silence, which means that I moved into a word. */
if (consecutiveVoiceDuration >= minimumWordLength && currentState == STATE_IN_SILENCE) {
iWordsCount++;
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "AMD: Word detected. iWordsCount:%d\n", iWordsCount);
previousState = currentState;
currentState = STATE_IN_WORD;
}
if (iWordsCount >= maximumNumberOfWords) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "AMD: ANSWERING MACHINE: iWordsCount:%d\n", iWordsCount);
ast_frfree(f);
strcpy(amdStatus , "MACHINE");
sprintf(amdCause , "MAXWORDS-%d-%d", iWordsCount, maximumNumberOfWords);
res = 1;
break;
}
if (inGreeting == 1 && voiceDuration >= greeting) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "AMD: ANSWERING MACHINE: voiceDuration:%d greeting:%d\n", voiceDuration, greeting);
ast_frfree(f);
strcpy(amdStatus , "MACHINE");
sprintf(amdCause , "LONGGREETING-%d-%d", voiceDuration, greeting);
res = 1;
break;
}
if (voiceDuration >= minimumWordLength ) {
silenceDuration = 0;
inInitialSilence = 0;
inGreeting = 1;
}
}
}
ast_frfree(f);
}
if (!res) {
/* It took too long to get a frame back. Giving up. */
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "AMD: Channel [%s]. Too long...\n", chan->name);
strcpy(amdStatus , "NOTSURE");
sprintf(amdCause , "TOOLONG-%d", iTotalTime);
}
/* Set the status and cause on the channel */
pbx_builtin_setvar_helper(chan , "AMDSTATUS" , amdStatus);
pbx_builtin_setvar_helper(chan , "AMDCAUSE" , amdCause);
/* Restore channel read format */
if (readFormat && ast_set_read_format(chan, readFormat))
ast_log(LOG_WARNING, "AMD: Unable to restore read format on '%s'\n", chan->name);
/* Free the DSP used to detect silence */
ast_dsp_free(silenceDetector);
return;
}
static int amd_exec(struct ast_channel *chan, void *data)
{
struct ast_module_user *u = NULL;
u = ast_module_user_add(chan);
isAnsweringMachine(chan, data);
ast_module_user_remove(u);
return 0;
}
static void load_config(void)
{
struct ast_config *cfg = NULL;
char *cat = NULL;
struct ast_variable *var = NULL;
if (!(cfg = ast_config_load("amd.conf"))) {
ast_log(LOG_ERROR, "Configuration file amd.conf missing.\n");
return;
}
cat = ast_category_browse(cfg, NULL);
while (cat) {
if (!strcasecmp(cat, "general") ) {
var = ast_variable_browse(cfg, cat);
while (var) {
if (!strcasecmp(var->name, "initial_silence")) {
dfltInitialSilence = atoi(var->value);
} else if (!strcasecmp(var->name, "greeting")) {
dfltGreeting = atoi(var->value);
} else if (!strcasecmp(var->name, "after_greeting_silence")) {
dfltAfterGreetingSilence = atoi(var->value);
} else if (!strcasecmp(var->name, "silence_threshold")) {
dfltSilenceThreshold = atoi(var->value);
} else if (!strcasecmp(var->name, "total_analysis_time")) {
dfltTotalAnalysisTime = atoi(var->value);
} else if (!strcasecmp(var->name, "min_word_length")) {
dfltMinimumWordLength = atoi(var->value);
} else if (!strcasecmp(var->name, "between_words_silence")) {
dfltBetweenWordsSilence = atoi(var->value);
} else if (!strcasecmp(var->name, "maximum_number_of_words")) {
dfltMaximumNumberOfWords = atoi(var->value);
} else {
ast_log(LOG_WARNING, "%s: Cat:%s. Unknown keyword %s at line %d of amd.conf\n",
app, cat, var->name, var->lineno);
}
var = var->next;
}
}
cat = ast_category_browse(cfg, cat);
}
ast_config_destroy(cfg);
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "AMD defaults: initialSilence [%d] greeting [%d] afterGreetingSilence [%d] "
"totalAnalysisTime [%d] minimumWordLength [%d] betweenWordsSilence [%d] maximumNumberOfWords [%d] silenceThreshold [%d] \n",
dfltInitialSilence, dfltGreeting, dfltAfterGreetingSilence, dfltTotalAnalysisTime,
dfltMinimumWordLength, dfltBetweenWordsSilence, dfltMaximumNumberOfWords, dfltSilenceThreshold );
return;
}
static int unload_module(void)
{
ast_module_user_hangup_all();
return ast_unregister_application(app);
}
static int load_module(void)
{
load_config();
return ast_register_application(app, amd_exec, synopsis, descrip);
}
static int reload(void)
{
load_config();
return 0;
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Answering Machine Detection Application",
.load = load_module,
.unload = unload_module,
.reload = reload,
);

View File

@@ -17,24 +17,21 @@
*/
/*! \file
*
* \brief Execute arbitrary authenticate commands
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
@@ -44,33 +41,17 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/app.h"
#include "asterisk/astdb.h"
#include "asterisk/utils.h"
#include "asterisk/options.h"
enum {
OPT_ACCOUNT = (1 << 0),
OPT_DATABASE = (1 << 1),
OPT_JUMP = (1 << 2),
OPT_MULTIPLE = (1 << 3),
OPT_REMOVE = (1 << 4),
} auth_option_flags;
AST_APP_OPTIONS(auth_app_options, {
AST_APP_OPTION('a', OPT_ACCOUNT),
AST_APP_OPTION('d', OPT_DATABASE),
AST_APP_OPTION('j', OPT_JUMP),
AST_APP_OPTION('m', OPT_MULTIPLE),
AST_APP_OPTION('r', OPT_REMOVE),
});
static char *tdesc = "Authentication Application";
static char *app = "Authenticate";
static char *synopsis = "Authenticate a user";
static char *descrip =
" Authenticate(password[|options[|maxdigits]]): This application asks the caller\n"
"to enter a given password in order to continue dialplan execution. If the password\n"
"begins with the '/' character, it is interpreted as a file which contains a list of\n"
" Authenticate(password[|options]): This application asks the caller to enter a\n"
"given password in order to continue dialplan execution. If the password begins\n"
"with the '/' character, it is interpreted as a file which contains a list of\n"
"valid passwords, listed 1 password per line in the file.\n"
" When using a database key, the value associated with the key can be anything.\n"
"Users have three attempts to authenticate before the channel is hung up. If the\n"
@@ -85,96 +66,79 @@ static char *descrip =
" the file. When one of the passwords is matched, the channel will have\n"
" its account code set to the corresponding account code in the file.\n"
" r - Remove the database key upon successful entry (valid with 'd' only)\n"
" maxdigits - maximum acceptable number of digits. Stops reading after\n"
" maxdigits have been entered (without requiring the user to\n"
" press the '#' key).\n"
" Defaults to 0 - no limit - wait for the user press the '#' key.\n"
;
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int auth_exec(struct ast_channel *chan, void *data)
{
int res=0;
int jump = 0;
int retries;
struct ast_module_user *u;
struct localuser *u;
char password[256]="";
char passwd[256];
char *opts;
char *prompt;
int maxdigits;
char *argcopy =NULL;
struct ast_flags flags = {0};
AST_DECLARE_APP_ARGS(arglist,
AST_APP_ARG(password);
AST_APP_ARG(options);
AST_APP_ARG(maxdigits);
);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Authenticate requires an argument(password)\n");
return -1;
}
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
if (chan->_state != AST_STATE_UP) {
res = ast_answer(chan);
if (res) {
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
}
argcopy = ast_strdupa(data);
AST_STANDARD_APP_ARGS(arglist,argcopy);
if (!ast_strlen_zero(arglist.options)) {
ast_app_parse_options(auth_app_options, &flags, NULL, arglist.options);
}
if (!ast_strlen_zero(arglist.maxdigits)) {
maxdigits = atoi(arglist.maxdigits);
if ((maxdigits<1) || (maxdigits>sizeof(passwd)-2))
maxdigits = sizeof(passwd) - 2;
} else {
maxdigits = sizeof(passwd) - 2;
}
strncpy(password, data, sizeof(password) - 1);
opts=strchr(password, '|');
if (opts) {
*opts = 0;
opts++;
} else
opts = "";
if (strchr(opts, 'j'))
jump = 1;
/* Start asking for password */
prompt = "agent-pass";
for (retries = 0; retries < 3; retries++) {
res = ast_app_getdata(chan, prompt, passwd, maxdigits, 0);
res = ast_app_getdata(chan, prompt, passwd, sizeof(passwd) - 2, 0);
if (res < 0)
break;
res = 0;
if (arglist.password[0] == '/') {
if (ast_test_flag(&flags,OPT_DATABASE)) {
if (password[0] == '/') {
if (strchr(opts, 'd')) {
char tmp[256];
/* Compare against a database key */
if (!ast_db_get(arglist.password + 1, passwd, tmp, sizeof(tmp))) {
if (!ast_db_get(password + 1, passwd, tmp, sizeof(tmp))) {
/* It's a good password */
if (ast_test_flag(&flags,OPT_REMOVE)) {
ast_db_del(arglist.password + 1, passwd);
if (strchr(opts, 'r')) {
ast_db_del(password + 1, passwd);
}
break;
}
} else {
/* Compare against a file */
FILE *f;
f = fopen(arglist.password, "r");
f = fopen(password, "r");
if (f) {
char buf[256] = "";
char md5passwd[33] = "";
char *md5secret = NULL;
while (!feof(f)) {
if (!fgets(buf, sizeof(buf), f)) {
continue;
}
if (!ast_strlen_zero(buf)) {
size_t len = strlen(buf);
if (buf[len - 1] == '\n')
buf[len - 1] = '\0';
if (ast_test_flag(&flags,OPT_MULTIPLE)) {
fgets(buf, sizeof(buf), f);
if (!feof(f) && !ast_strlen_zero(buf)) {
buf[strlen(buf) - 1] = '\0';
if (strchr(opts, 'm')) {
md5secret = strchr(buf, ':');
if (md5secret == NULL)
continue;
@@ -182,13 +146,13 @@ static int auth_exec(struct ast_channel *chan, void *data)
md5secret++;
ast_md5_hash(md5passwd, passwd);
if (!strcmp(md5passwd, md5secret)) {
if (ast_test_flag(&flags,OPT_ACCOUNT))
if (strchr(opts, 'a'))
ast_cdr_setaccount(chan, buf);
break;
}
} else {
if (!strcmp(passwd, buf)) {
if (ast_test_flag(&flags,OPT_ACCOUNT))
if (strchr(opts, 'a'))
ast_cdr_setaccount(chan, buf);
break;
}
@@ -197,7 +161,7 @@ static int auth_exec(struct ast_channel *chan, void *data)
}
fclose(f);
if (!ast_strlen_zero(buf)) {
if (ast_test_flag(&flags,OPT_MULTIPLE)) {
if (strchr(opts, 'm')) {
if (md5secret && !strcmp(md5passwd, md5secret))
break;
} else {
@@ -206,23 +170,23 @@ static int auth_exec(struct ast_channel *chan, void *data)
}
}
} else
ast_log(LOG_WARNING, "Unable to open file '%s' for authentication: %s\n", arglist.password, strerror(errno));
ast_log(LOG_WARNING, "Unable to open file '%s' for authentication: %s\n", password, strerror(errno));
}
} else {
/* Compare against a fixed password */
if (!strcmp(passwd, arglist.password))
if (!strcmp(passwd, password))
break;
}
prompt="auth-incorrect";
}
if ((retries < 3) && !res) {
if (ast_test_flag(&flags,OPT_ACCOUNT) && !ast_test_flag(&flags,OPT_MULTIPLE))
if (strchr(opts, 'a') && !strchr(opts, 'm'))
ast_cdr_setaccount(chan, passwd);
res = ast_streamfile(chan, "auth-thankyou", chan->language);
if (!res)
res = ast_waitstream(chan, "");
} else {
if (ast_test_flag(&flags,OPT_JUMP) && ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101) == 0) {
if (jump && ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101)) {
res = 0;
} else {
if (!ast_streamfile(chan, "vm-goodbye", chan->language))
@@ -230,25 +194,39 @@ static int auth_exec(struct ast_channel *chan, void *data)
res = -1;
}
}
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
ast_module_user_hangup_all();
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, auth_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Authentication Application");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -17,25 +17,25 @@
*/
/*! \file
*
* \brief Applications connected with CDR engine
*
* Martin Pycko <martinp@digium.com>
*
* \ingroup applications
*/
#include <sys/types.h>
#include <stdlib.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <sys/types.h>
#include <stdlib.h>
#include "asterisk/channel.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
static char *tdesc = "Tell Asterisk to not maintain a CDR for the current call";
static char *nocdr_descrip =
" NoCDR(): This application will tell Asterisk not to maintain a CDR for the\n"
"current call.\n";
@@ -43,36 +43,55 @@ static char *nocdr_descrip =
static char *nocdr_app = "NoCDR";
static char *nocdr_synopsis = "Tell Asterisk to not maintain a CDR for the current call";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int nocdr_exec(struct ast_channel *chan, void *data)
{
struct ast_module_user *u;
struct localuser *u;
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
if (chan->cdr) {
ast_set_flag(chan->cdr, AST_CDR_FLAG_POST_DISABLED);
ast_cdr_free(chan->cdr);
chan->cdr = NULL;
}
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return 0;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(nocdr_app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(nocdr_app, nocdr_exec, nocdr_synopsis, nocdr_descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Tell Asterisk to not maintain a CDR for the current call");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -18,19 +18,11 @@
*/
/*! \file
*
* \brief Check if Channel is Available
*
* \author Mark Spencer <markster@digium.com>
* \author James Golovich <james@gnuinter.net>
* \brief Check if Channel is Available
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -38,6 +30,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <errno.h>
#include <sys/ioctl.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
@@ -48,6 +44,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/devicestate.h"
#include "asterisk/options.h"
static char *tdesc = "Check channel availability";
static char *app = "ChanIsAvail";
static char *synopsis = "Check channel availability";
@@ -63,37 +61,36 @@ static char *descrip =
" s - Consider the channel unavailable if the channel is in use at all\n"
" j - Support jumping to priority n+101 if no channel is available\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int chanavail_exec(struct ast_channel *chan, void *data)
{
int res=-1, inuse=-1, option_state=0, priority_jump=0;
int status;
struct ast_module_user *u;
char *info, tmp[512], trychan[512], *peers, *tech, *number, *rest, *cur;
struct localuser *u;
char *info, tmp[512], trychan[512], *peers, *tech, *number, *rest, *cur, *options, *stringp;
struct ast_channel *tempchan;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(reqchans);
AST_APP_ARG(options);
);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "ChanIsAvail requires an argument (Zap/1&Zap/2)\n");
return -1;
}
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
info = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, info);
if (args.options) {
if (strchr(args.options, 's'))
stringp = info;
strsep(&stringp, "|");
options = strsep(&stringp, "|");
if (options) {
if (strchr(options, 's'))
option_state = 1;
if (strchr(args.options, 'j'))
if (strchr(options, 'j'))
priority_jump = 1;
}
peers = args.reqchans;
peers = info;
if (peers) {
cur = peers;
do {
@@ -107,7 +104,7 @@ static int chanavail_exec(struct ast_channel *chan, void *data)
number = strchr(tech, '/');
if (!number) {
ast_log(LOG_WARNING, "ChanIsAvail argument takes format ([technology]/[device])\n");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
*number = '\0';
@@ -142,32 +139,47 @@ static int chanavail_exec(struct ast_channel *chan, void *data)
if (res < 1) {
pbx_builtin_setvar_helper(chan, "AVAILCHAN", "");
pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", "");
if (priority_jump || ast_opt_priority_jumping) {
if (priority_jump || option_priority_jumping) {
if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101)) {
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
}
}
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return 0;
}
static int unload_module(void)
int unload_module(void)
{
int res = 0;
res = ast_unregister_application(app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, chanavail_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Check channel availability");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,145 +0,0 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2006, Sergey Basmanov
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief ChannelRedirect application
*
* \author Sergey Basmanov <sergey_basmanov@mail.ru>
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/app.h"
#include "asterisk/features.h"
#include "asterisk/options.h"
static char *app = "ChannelRedirect";
static char *synopsis = "Redirects given channel to a dialplan target.";
static char *descrip =
"ChannelRedirect(channel|[[context|]extension|]priority):\n"
" Sends the specified channel to the specified extension priority\n";
static int asyncgoto_exec(struct ast_channel *chan, void *data)
{
int res = -1;
struct ast_module_user *u;
char *info, *context, *exten, *priority;
int prio = 1;
struct ast_channel *chan2 = NULL;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(channel);
AST_APP_ARG(label);
);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "%s requires an argument (channel|[[context|]exten|]priority)\n", app);
return -1;
}
u = ast_module_user_add(chan);
info = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, info);
if (ast_strlen_zero(args.channel) || ast_strlen_zero(args.label)) {
ast_log(LOG_WARNING, "%s requires an argument (channel|[[context|]exten|]priority)\n", app);
goto quit;
}
chan2 = ast_get_channel_by_name_locked(args.channel);
if (!chan2) {
ast_log(LOG_WARNING, "No such channel: %s\n", args.channel);
goto quit;
}
/* Parsed right to left, so standard parsing won't work */
context = strsep(&args.label, "|");
exten = strsep(&args.label, "|");
if (exten) {
priority = strsep(&args.label, "|");
if (!priority) {
priority = exten;
exten = context;
context = NULL;
}
} else {
priority = context;
context = NULL;
}
/* ast_findlabel_extension does not convert numeric priorities; it only does a lookup */
if (!(prio = atoi(priority)) && !(prio = ast_findlabel_extension(chan2, S_OR(context, chan2->context),
S_OR(exten, chan2->exten), priority, chan2->cid.cid_num))) {
ast_log(LOG_WARNING, "'%s' is not a known priority or label\n", priority);
goto chanquit;
}
if (option_debug > 1)
ast_log(LOG_DEBUG, "Attempting async goto (%s) to %s|%s|%d\n", args.channel, S_OR(context, chan2->context), S_OR(exten, chan2->exten), prio);
if (chan2->pbx) {
ast_channel_lock(chan2);
ast_set_flag(chan2, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
ast_channel_unlock(chan2);
}
if (ast_async_goto_if_exists(chan2, S_OR(context, chan2->context), S_OR(exten, chan2->exten), prio))
ast_log(LOG_WARNING, "%s failed for %s\n", app, args.channel);
else
res = 0;
chanquit:
ast_mutex_unlock(&chan2->lock);
quit:
ast_module_user_remove(u);
return res;
}
static int unload_module(void)
{
int res;
res = ast_unregister_application(app);
ast_module_user_hangup_all();
return res;
}
static int load_module(void)
{
return ast_register_application(app, asyncgoto_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Channel Redirect");

File diff suppressed because it is too large Load Diff

View File

@@ -17,22 +17,19 @@
*/
/*! \file
*
* \brief Trivial application to control playback of a sound file
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
@@ -44,6 +41,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/utils.h"
#include "asterisk/options.h"
static const char *tdesc = "Control Playback Application";
static const char *app = "ControlPlayback";
static const char *synopsis = "Play a file with fast forward and rewind";
@@ -66,6 +65,9 @@ static const char *descrip =
" CPLAYBACKSTATUS - This variable contains the status of the attempt as a text\n"
" string, one of: SUCCESS | USERSTOPPED | ERROR\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int is_on_phonepad(char key)
{
@@ -76,7 +78,7 @@ static int controlplayback_exec(struct ast_channel *chan, void *data)
{
int res = 0, priority_jump = 0;
int skipms = 0;
struct ast_module_user *u;
struct localuser *u;
char *tmp;
int argc;
char *argv[8];
@@ -96,7 +98,7 @@ static int controlplayback_exec(struct ast_channel *chan, void *data)
return -1;
}
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
tmp = ast_strdupa(data);
memset(argv, 0, sizeof(argv));
@@ -105,7 +107,7 @@ static int controlplayback_exec(struct ast_channel *chan, void *data)
if (argc < 1) {
ast_log(LOG_WARNING, "ControlPlayback requires an argument (filename)\n");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
@@ -132,12 +134,12 @@ static int controlplayback_exec(struct ast_channel *chan, void *data)
res = ast_control_streamfile(chan, argv[arg_file], argv[arg_fwd], argv[arg_rev], argv[arg_stop], argv[arg_pause], argv[arg_restart], skipms);
/* If we stopped on one of our stop keys, return 0 */
if (res > 0 && argv[arg_stop] && strchr(argv[arg_stop], res)) {
if (argv[arg_stop] && strchr(argv[arg_stop], res)) {
res = 0;
pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "USERSTOPPED");
} else {
if (res < 0) {
if (priority_jump || ast_opt_priority_jumping) {
if (priority_jump || option_priority_jumping) {
if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101)) {
ast_log(LOG_WARNING, "ControlPlayback tried to jump to priority n+101 as requested, but priority didn't exist\n");
}
@@ -148,21 +150,41 @@ static int controlplayback_exec(struct ast_channel *chan, void *data)
pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "SUCCESS");
}
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, controlplayback_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Control Playback Application");
char *description(void)
{
return (char *) tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

256
apps/app_curl.c Normal file
View File

@@ -0,0 +1,256 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2004 - 2005, Tilghman Lesher
*
* Tilghman Lesher <curl-20050919@the-tilghman.com>
* and Brian Wilkins <bwilkins@cfl.rr.com> (Added POST option)
*
* app_curl.c is distributed with no restrictions on usage or
* redistribution.
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
*/
/*! \file
* \brief Curl - App to load a URL
*
* \ingroup applications
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/cli.h"
#include "asterisk/options.h"
#include "asterisk/module.h"
static char *tdesc = "Load external URL";
static char *app = "Curl";
static char *synopsis = "Load an external URL";
static char *descrip =
" Curl(URL[|postdata]): This application will request the specified URL.\n"
"It is mainly used for signalling external applications of an event.\n"
"Parameters:\n"
" URL - This is the external URL to request.\n"
" postdata - This information will be treated as POST data.\n"
"This application will set the following variable:\n"
" CURL - This variable will contain the resulting page.\n"
"This application has been deprecated in favor of the CURL function.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
struct MemoryStruct {
char *memory;
size_t size;
};
static void *myrealloc(void *ptr, size_t size)
{
/* There might be a realloc() out there that doesn't like reallocing
NULL pointers, so we take care of it here */
if (ptr)
return realloc(ptr, size);
else
return malloc(size);
}
static size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
{
register int realsize = size * nmemb;
struct MemoryStruct *mem = (struct MemoryStruct *)data;
mem->memory = (char *)myrealloc(mem->memory, mem->size + realsize + 1);
if (mem->memory) {
memcpy(&(mem->memory[mem->size]), ptr, realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;
}
return realsize;
}
static int curl_internal(struct MemoryStruct *chunk, char *url, char *post)
{
CURL *curl;
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if (!curl) {
return -1;
}
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)chunk);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "asterisk-libcurl-agent/1.0");
if (post) {
curl_easy_setopt(curl, CURLOPT_POST, 1);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post);
}
curl_easy_perform(curl);
curl_easy_cleanup(curl);
return 0;
}
static int curl_exec(struct ast_channel *chan, void *data)
{
int res = 0;
struct localuser *u;
char *info, *post_data=NULL, *url;
struct MemoryStruct chunk = { NULL, 0 };
static int dep_warning = 0;
if (!dep_warning) {
ast_log(LOG_WARNING, "The application Curl is deprecated. Please use the CURL() function instead.\n");
dep_warning = 1;
}
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Curl requires an argument (URL)\n");
return -1;
}
LOCAL_USER_ADD(u);
if ((info = ast_strdupa(data))) {
url = strsep(&info, "|");
post_data = info;
} else {
ast_log(LOG_ERROR, "Out of memory\n");
LOCAL_USER_REMOVE(u);
return -1;
}
if (! curl_internal(&chunk, url, post_data)) {
if (chunk.memory) {
chunk.memory[chunk.size] = '\0';
if (chunk.memory[chunk.size - 1] == 10)
chunk.memory[chunk.size - 1] = '\0';
pbx_builtin_setvar_helper(chan, "CURL", chunk.memory);
free(chunk.memory);
}
} else {
ast_log(LOG_ERROR, "Cannot allocate curl structure\n");
res = -1;
}
LOCAL_USER_REMOVE(u);
return res;
}
static char *acf_curl_exec(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
{
struct localuser *u;
char *info, *post_data=NULL, *url;
struct MemoryStruct chunk = { NULL, 0 };
*buf = '\0';
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "CURL requires an argument (URL)\n");
return buf;
}
LOCAL_USER_ACF_ADD(u);
info = ast_strdupa(data);
if (!info) {
ast_log(LOG_ERROR, "Out of memory\n");
LOCAL_USER_REMOVE(u);
return buf;
}
url = strsep(&info, "|");
post_data = info;
if (! curl_internal(&chunk, url, post_data)) {
if (chunk.memory) {
chunk.memory[chunk.size] = '\0';
if (chunk.memory[chunk.size - 1] == 10)
chunk.memory[chunk.size - 1] = '\0';
ast_copy_string(buf, chunk.memory, len);
free(chunk.memory);
}
} else {
ast_log(LOG_ERROR, "Cannot allocate curl structure\n");
}
LOCAL_USER_REMOVE(u);
return buf;
}
struct ast_custom_function acf_curl = {
.name = "CURL",
.synopsis = "Retrieves the contents of a URL",
.syntax = "CURL(url[|post-data])",
.desc =
" url - URL to retrieve\n"
" post-data - Optional data to send as a POST (GET is default action)\n",
.read = acf_curl_exec,
};
int unload_module(void)
{
int res;
res = ast_custom_function_unregister(&acf_curl);
res |= ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
int load_module(void)
{
int res;
res = ast_custom_function_register(&acf_curl);
res |= ast_register_application(app, curl_exec, synopsis, descrip);
return res;
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,7 +1,7 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (c) 2003-2006 Tilghman Lesher. All rights reserved.
* Copyright (c) 2003 Tilghman Lesher. All rights reserved.
*
* Tilghman Lesher <app_cut__v003@the-tilghman.com>
*
@@ -16,23 +16,20 @@
*/
/*! \file
*
* \brief CUT function
* \brief Cut application
*
* \author Tilghman Lesher <app_cut__v003@the-tilghman.com>
*
* \ingroup functions
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
@@ -44,6 +41,37 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
/* Maximum length of any variable */
#define MAXRESULT 1024
static char *tdesc = "Cut out information from a string";
static char *app_cut = "Cut";
static char *cut_synopsis = "Splits a variable's contents using the specified delimiter";
static char *cut_descrip =
" Cut(newvar=varname,delimiter,fieldspec): This applicaiton will split the\n"
"contents of a variable based on the given delimeter and store the result in\n"
"a new variable.\n"
"Parameters:\n"
" newvar - new variable created from result string\n"
" varname - variable you want cut\n"
" delimiter - defaults to '-'\n"
" fieldspec - number of the field you want (1-based offset)\n"
" may also be specified as a range (with -)\n"
" or group of ranges and fields (with &)\n"
"This application has been deprecated in favor of the CUT function.\n";
static char *app_sort = "Sort";
static char *app_sort_synopsis = "Sorts a list of keywords and values";
static char *app_sort_descrip =
" Sort(newvar=key1:val1[,key2:val2[[...],keyN:valN]]): This application will\n"
"sort the list provided in ascending order. The result will be stored in the\n"
"specified variable name.\n"
" This applicaiton has been deprecated in favor of the SORT function.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
struct sortable_keys {
char *key;
float value;
@@ -52,12 +80,13 @@ struct sortable_keys {
static int sort_subroutine(const void *arg1, const void *arg2)
{
const struct sortable_keys *one=arg1, *two=arg2;
if (one->value < two->value)
if (one->value < two->value) {
return -1;
else if (one->value == two->value)
} else if (one->value == two->value) {
return 0;
else
} else {
return 1;
}
}
#define ERROR_NOARG (-1)
@@ -72,17 +101,25 @@ static int sort_internal(struct ast_channel *chan, char *data, char *buffer, siz
memset(buffer, 0, buflen);
if (!data)
if (!data) {
return ERROR_NOARG;
}
strings = ast_strdupa(data);
strings = ast_strdupa((char *)data);
if (!strings) {
return ERROR_NOMEM;
}
for (ptrkey = strings; *ptrkey; ptrkey++) {
if (*ptrkey == '|')
if (*ptrkey == '|') {
count++;
}
}
sortable_keys = alloca(count * sizeof(struct sortable_keys));
if (!sortable_keys) {
return ERROR_NOMEM;
}
memset(sortable_keys, 0, count * sizeof(struct sortable_keys));
@@ -94,7 +131,8 @@ static int sort_internal(struct ast_channel *chan, char *data, char *buffer, siz
count--;
continue;
}
*ptrvalue++ = '\0';
*ptrvalue = '\0';
ptrvalue++;
sortable_keys[count2].key = ptrkey;
sscanf(ptrvalue, "%f", &sortable_keys[count2].value);
count2++;
@@ -117,47 +155,42 @@ static int sort_internal(struct ast_channel *chan, char *data, char *buffer, siz
static int cut_internal(struct ast_channel *chan, char *data, char *buffer, size_t buflen)
{
char *parse;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(varname);
AST_APP_ARG(delimiter);
AST_APP_ARG(field);
);
char *s, *args[3], *varname=NULL, *delimiter=NULL, *field=NULL;
int args_okay = 0;
memset(buffer, 0, buflen);
parse = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, parse);
memset(buffer, 0, buflen);
/* Check and parse arguments */
if(args.argc < 3){
return ERROR_NOARG;
} else {
if (data) {
s = ast_strdupa((char *)data);
if (s) {
ast_app_separate_args(s, '|', args, 3);
varname = args[0];
delimiter = args[1];
field = args[2];
if (field) {
args_okay = 1;
}
} else {
return ERROR_NOMEM;
}
}
if (args_okay) {
char d, ds[2];
char *tmp = alloca(strlen(args.varname) + 4);
char *tmp = alloca(strlen(varname) + 4);
char varvalue[MAXRESULT], *tmp2=varvalue;
if (tmp) {
snprintf(tmp, strlen(args.varname) + 4, "${%s}", args.varname);
snprintf(tmp, strlen(varname) + 4, "${%s}", varname);
memset(varvalue, 0, sizeof(varvalue));
} else {
return ERROR_NOMEM;
}
if (args.delimiter[0] == '\\') {
if (args.delimiter[1] == 'n')
d = '\n';
else if (args.delimiter[1] == 't')
d = '\t';
else if (args.delimiter[1] == 'r')
d = '\r';
else if (args.delimiter[1])
d = args.delimiter[1];
else
d = '-';
} else if (args.delimiter[0])
d = args.delimiter[0];
if (delimiter[0])
d = delimiter[0];
else
d = '-';
@@ -168,8 +201,8 @@ static int cut_internal(struct ast_channel *chan, char *data, char *buffer, size
if (tmp2) {
int curfieldnum = 1;
while (tmp2 != NULL && args.field != NULL) {
char *nextgroup = strsep(&(args.field), "&");
while ((tmp2 != NULL) && (field != NULL)) {
char *nextgroup = strsep(&field, "&");
int num1 = 0, num2 = MAXRESULT;
char trashchar;
@@ -190,44 +223,146 @@ static int cut_internal(struct ast_channel *chan, char *data, char *buffer, size
/* Get to start, if any */
if (num1 > 0) {
while (tmp2 != (char *)NULL + 1 && curfieldnum < num1) {
while ((tmp2 != (char *)NULL + 1) && (curfieldnum < num1)) {
tmp2 = index(tmp2, d) + 1;
curfieldnum++;
}
}
/* Most frequent problem is the expectation of reordering fields */
if ((num1 > 0) && (curfieldnum > num1))
if ((num1 > 0) && (curfieldnum > num1)) {
ast_log(LOG_WARNING, "We're already past the field you wanted?\n");
}
/* Re-null tmp2 if we added 1 to NULL */
if (tmp2 == (char *)NULL + 1)
tmp2 = NULL;
/* Output fields until we either run out of fields or num2 is reached */
while (tmp2 != NULL && curfieldnum <= num2) {
while ((tmp2 != NULL) && (curfieldnum <= num2)) {
char *tmp3 = strsep(&tmp2, ds);
int curlen = strlen(buffer);
if (curlen)
if (curlen) {
snprintf(buffer + curlen, buflen - curlen, "%c%s", d, tmp3);
else
} else {
snprintf(buffer, buflen, "%s", tmp3);
}
curfieldnum++;
}
}
}
} else {
return ERROR_NOARG;
}
return 0;
}
static int acf_sort_exec(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
static int sort_exec(struct ast_channel *chan, void *data)
{
struct ast_module_user *u;
int ret = -1;
int res=0;
struct localuser *u;
char *varname, *strings, result[512] = "";
static int dep_warning=0;
u = ast_module_user_add(chan);
if (!dep_warning) {
ast_log(LOG_WARNING, "The application Sort is deprecated. Please use the SORT() function instead.\n");
dep_warning=1;
}
if (!data) {
ast_log(LOG_ERROR, "Sort() requires an argument\n");
return 0;
}
LOCAL_USER_ADD(u);
strings = ast_strdupa((char *)data);
if (!strings) {
ast_log(LOG_ERROR, "Out of memory\n");
LOCAL_USER_REMOVE(u);
return 0;
}
varname = strsep(&strings, "=");
switch (sort_internal(chan, strings, result, sizeof(result))) {
case ERROR_NOARG:
ast_log(LOG_ERROR, "Sort() requires an argument\n");
res = 0;
break;
case ERROR_NOMEM:
ast_log(LOG_ERROR, "Out of memory\n");
res = -1;
break;
case 0:
pbx_builtin_setvar_helper(chan, varname, result);
res = 0;
break;
default:
ast_log(LOG_ERROR, "Unknown internal error\n");
res = -1;
}
LOCAL_USER_REMOVE(u);
return res;
}
static int cut_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
char *s, *newvar=NULL, result[512];
static int dep_warning = 0;
LOCAL_USER_ADD(u);
if (!dep_warning) {
ast_log(LOG_WARNING, "The application Cut is deprecated. Please use the CUT() function instead.\n");
dep_warning=1;
}
/* Check and parse arguments */
if (data) {
s = ast_strdupa((char *)data);
if (s) {
newvar = strsep(&s, "=");
} else {
ast_log(LOG_ERROR, "Out of memory\n");
LOCAL_USER_REMOVE(u);
return -1;
}
}
switch (cut_internal(chan, s, result, sizeof(result))) {
case ERROR_NOARG:
ast_log(LOG_ERROR, "Cut() requires an argument\n");
res = 0;
break;
case ERROR_NOMEM:
ast_log(LOG_ERROR, "Out of memory\n");
res = -1;
break;
case ERROR_USAGE:
ast_log(LOG_ERROR, "Usage: %s\n", cut_synopsis);
res = 0;
break;
case 0:
pbx_builtin_setvar_helper(chan, newvar, result);
res = 0;
break;
default:
ast_log(LOG_ERROR, "Unknown internal error\n");
res = -1;
}
LOCAL_USER_REMOVE(u);
return res;
}
static char *acf_sort_exec(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
{
struct localuser *u;
LOCAL_USER_ACF_ADD(u);
switch (sort_internal(chan, data, buf, len)) {
case ERROR_NOARG:
@@ -237,48 +372,37 @@ static int acf_sort_exec(struct ast_channel *chan, char *cmd, char *data, char *
ast_log(LOG_ERROR, "Out of memory\n");
break;
case 0:
ret = 0;
break;
default:
ast_log(LOG_ERROR, "Unknown internal error\n");
}
ast_module_user_remove(u);
return ret;
LOCAL_USER_REMOVE(u);
return buf;
}
static int acf_cut_exec(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
static char *acf_cut_exec(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
{
int ret = -1;
struct ast_module_user *u = NULL;
struct localuser *u;
if (chan) {
u = ast_module_user_add(chan);
}
LOCAL_USER_ACF_ADD(u);
switch (cut_internal(chan, data, buf, len)) {
case ERROR_NOARG:
ast_log(LOG_ERROR, "Syntax: CUT(<varname>,<char-delim>,<range-spec>) - missing argument!\n");
ast_log(LOG_ERROR, "CUT() requires an argument\n");
break;
case ERROR_NOMEM:
ast_log(LOG_ERROR, "Out of memory\n");
break;
case ERROR_USAGE:
ast_log(LOG_ERROR, "Usage: CUT(<varname>,<char-delim>,<range-spec>)\n");
ast_log(LOG_ERROR, "Usage: %s\n", cut_synopsis);
break;
case 0:
ret = 0;
break;
default:
ast_log(LOG_ERROR, "Unknown internal error\n");
}
if (chan) {
ast_module_user_remove(u);
}
return ret;
LOCAL_USER_REMOVE(u);
return buf;
}
struct ast_custom_function acf_sort = {
@@ -305,26 +429,45 @@ struct ast_custom_function acf_cut = {
.read = acf_cut_exec,
};
static int unload_module(void)
int unload_module(void)
{
int res = 0;
int res;
res |= ast_custom_function_unregister(&acf_cut);
res = ast_custom_function_unregister(&acf_cut);
res |= ast_custom_function_unregister(&acf_sort);
res |= ast_unregister_application(app_sort);
res |= ast_unregister_application(app_cut);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
int res = 0;
int res;
res |= ast_custom_function_register(&acf_cut);
res = ast_custom_function_register(&acf_cut);
res |= ast_custom_function_register(&acf_sort);
res |= ast_register_application(app_sort, sort_exec, app_sort_synopsis, app_sort_descrip);
res |= ast_register_application(app_cut, cut_exec, cut_synopsis, cut_descrip);
return res;
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Cut out information from a string");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

101
apps/app_datetime.c Normal file
View File

@@ -0,0 +1,101 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2005, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
* \brief Time of day - Report the time of day
*
* \ingroup applications
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/say.h"
static char *tdesc = "Date and Time";
static char *app = "DateTime";
static char *synopsis = "Say the date and time";
static char *descrip =
" DateTime(): This application will say the current date and time.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int datetime_exec(struct ast_channel *chan, void *data)
{
int res=0;
time_t t;
struct localuser *u;
LOCAL_USER_ADD(u);
time(&t);
if (chan->_state != AST_STATE_UP)
res = ast_answer(chan);
if (!res)
res = ast_say_datetime(chan, t, "", chan->language);
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
int load_module(void)
{
return ast_register_application(app, datetime_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -22,22 +22,19 @@
*
* \brief Database access functions
*
* \author Mark Spencer <markster@digium.com>
* \author Jefferson Noxon <jeff@debian.org>
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/options.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
@@ -48,38 +45,65 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/options.h"
/*! \todo XXX Remove this application after 1.4 is relased */
static char *tdesc = "Database Access Functions";
static char *g_descrip =
" DBget(varname=family/key[|options]): This application will retrieve a value\n"
"from the Asterisk database and store it in the given variable.\n"
" Options:\n"
" j - Jump to priority n+101 if the requested family/key isn't found.\n"
" This application sets the following channel variable upon completion:\n"
" DBGETSTATUS - This variable will contain the status of the attempt\n"
" FOUND | NOTFOUND \n"
" This application has been deprecated in favor of the DB function.\n";
static char *p_descrip =
" DBput(family/key=value): This application will store the given value in the\n"
"specified location in the Asterisk database.\n"
" This application has been deprecated in favor of the DB function.\n";
static char *d_descrip =
" DBdel(family/key): This application will delete a key from the Asterisk\n"
"database.\n"
" This application has been DEPRECATED in favor of the DB_DELETE function.\n";
" DBdel(family/key): This applicaiton will delete a key from the Asterisk\n"
"database.\n";
static char *dt_descrip =
" DBdeltree(family[/keytree]): This application will delete a family or keytree\n"
"from the Asterisk database\n";
static char *g_app = "DBget";
static char *p_app = "DBput";
static char *d_app = "DBdel";
static char *dt_app = "DBdeltree";
static char *g_synopsis = "Retrieve a value from the database";
static char *p_synopsis = "Store a value in the database";
static char *d_synopsis = "Delete a key from the database";
static char *dt_synopsis = "Delete a family or keytree from the database";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int deltree_exec(struct ast_channel *chan, void *data)
{
char *argv, *family, *keytree;
struct ast_module_user *u;
struct localuser *u;
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
argv = ast_strdupa(data);
if (!argv) {
ast_log(LOG_ERROR, "Memory allocation failed\n");
LOCAL_USER_REMOVE(u);
return 0;
}
if (strchr(argv, '/')) {
family = strsep(&argv, "/");
keytree = strsep(&argv, "\0");
if (!family || !keytree) {
ast_log(LOG_DEBUG, "Ignoring; Syntax error in argument\n");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return 0;
}
if (ast_strlen_zero(keytree))
@@ -101,7 +125,7 @@ static int deltree_exec(struct ast_channel *chan, void *data)
ast_verbose(VERBOSE_PREFIX_3 "DBdeltree: Error deleting key from database.\n");
}
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return 0;
}
@@ -109,24 +133,23 @@ static int deltree_exec(struct ast_channel *chan, void *data)
static int del_exec(struct ast_channel *chan, void *data)
{
char *argv, *family, *key;
struct ast_module_user *u;
static int deprecation_warning = 0;
struct localuser *u;
u = ast_module_user_add(chan);
if (!deprecation_warning) {
deprecation_warning = 1;
ast_log(LOG_WARNING, "The DBdel application has been deprecated in favor of the DB_DELETE dialplan function!\n");
}
LOCAL_USER_ADD(u);
argv = ast_strdupa(data);
if (!argv) {
ast_log (LOG_ERROR, "Memory allocation failed\n");
LOCAL_USER_REMOVE(u);
return 0;
}
if (strchr(argv, '/')) {
family = strsep(&argv, "/");
key = strsep(&argv, "\0");
if (!family || !key) {
ast_log(LOG_DEBUG, "Ignoring; Syntax error in argument\n");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return 0;
}
if (option_verbose > 2)
@@ -139,29 +162,162 @@ static int del_exec(struct ast_channel *chan, void *data)
ast_log(LOG_DEBUG, "Ignoring, no parameters\n");
}
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return 0;
}
static int unload_module(void)
static int put_exec(struct ast_channel *chan, void *data)
{
char *argv, *value, *family, *key;
static int dep_warning = 0;
struct localuser *u;
LOCAL_USER_ADD(u);
if (!dep_warning) {
ast_log(LOG_WARNING, "This application has been deprecated, please use the ${DB(family/key)} function instead.\n");
dep_warning = 1;
}
argv = ast_strdupa(data);
if (!argv) {
ast_log(LOG_ERROR, "Memory allocation failed\n");
LOCAL_USER_REMOVE(u);
return 0;
}
if (strchr(argv, '/') && strchr(argv, '=')) {
family = strsep(&argv, "/");
key = strsep(&argv, "=");
value = strsep(&argv, "\0");
if (!value || !family || !key) {
ast_log(LOG_DEBUG, "Ignoring; Syntax error in argument\n");
LOCAL_USER_REMOVE(u);
return 0;
}
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "DBput: family=%s, key=%s, value=%s\n", family, key, value);
if (ast_db_put(family, key, value)) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "DBput: Error writing value to database.\n");
}
} else {
ast_log (LOG_DEBUG, "Ignoring, no parameters\n");
}
LOCAL_USER_REMOVE(u);
return 0;
}
static int get_exec(struct ast_channel *chan, void *data)
{
char *argv, *varname, *family, *key, *options = NULL;
char dbresult[256];
static int dep_warning = 0;
int priority_jump = 0;
struct localuser *u;
LOCAL_USER_ADD(u);
if (!dep_warning) {
ast_log(LOG_WARNING, "This application has been deprecated, please use the ${DB(family/key)} function instead.\n");
dep_warning = 1;
}
argv = ast_strdupa(data);
if (!argv) {
ast_log(LOG_ERROR, "Memory allocation failed\n");
LOCAL_USER_REMOVE(u);
return 0;
}
if (strchr(argv, '=') && strchr(argv, '/')) {
varname = strsep(&argv, "=");
family = strsep(&argv, "/");
if (strchr((void *)&argv, '|')) {
key = strsep(&argv, "|");
options = strsep(&argv, "\0");
} else
key = strsep(&argv, "\0");
if (!varname || !family || !key) {
ast_log(LOG_DEBUG, "Ignoring; Syntax error in argument\n");
LOCAL_USER_REMOVE(u);
return 0;
}
if (options) {
if (strchr(options, 'j'))
priority_jump = 1;
}
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "DBget: varname=%s, family=%s, key=%s\n", varname, family, key);
if (!ast_db_get(family, key, dbresult, sizeof (dbresult) - 1)) {
pbx_builtin_setvar_helper(chan, varname, dbresult);
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "DBget: set variable %s to %s\n", varname, dbresult);
pbx_builtin_setvar_helper(chan, "DBGETSTATUS", "FOUND");
} else {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "DBget: Value not found in database.\n");
if (priority_jump || option_priority_jumping) {
/* Send the call to n+101 priority, where n is the current priority */
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
}
pbx_builtin_setvar_helper(chan, "DBGETSTATUS", "NOTFOUND");
}
} else {
ast_log(LOG_DEBUG, "Ignoring, no parameters\n");
}
LOCAL_USER_REMOVE(u);
return 0;
}
int unload_module(void)
{
int retval;
retval = ast_unregister_application(dt_app);
retval |= ast_unregister_application(d_app);
retval |= ast_unregister_application(p_app);
retval |= ast_unregister_application(g_app);
STANDARD_HANGUP_LOCALUSERS;
return retval;
}
static int load_module(void)
int load_module(void)
{
int retval;
retval = ast_register_application(d_app, del_exec, d_synopsis, d_descrip);
retval = ast_register_application(g_app, get_exec, g_synopsis, g_descrip);
retval |= ast_register_application(p_app, put_exec, p_synopsis, p_descrip);
retval |= ast_register_application(d_app, del_exec, d_synopsis, d_descrip);
retval |= ast_register_application(dt_app, deltree_exec, dt_synopsis, dt_descrip);
return retval;
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Database Access Functions");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

File diff suppressed because it is too large Load Diff

View File

@@ -22,20 +22,18 @@
*
* \brief Virtual Dictation Machine Application For Asterisk
*
* \author Anthony Minessale II <anthmct@yahoo.com>
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/stat.h> /* for mkdir */
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
@@ -46,12 +44,16 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/app.h"
static char *tdesc = "Virtual Dictation Machine";
static char *app = "Dictate";
static char *synopsis = "Virtual Dictation Machine";
static char *desc = " Dictate([<base_dir>[|<filename>]])\n"
static char *desc = " Dictate([<base_dir>])\n"
"Start dictation machine using optional base dir for files.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
typedef enum {
DFLAG_RECORD = (1 << 0),
DFLAG_PLAY = (1 << 1),
@@ -78,20 +80,16 @@ static int play_and_wait(struct ast_channel *chan, char *file, char *digits)
static int dictate_exec(struct ast_channel *chan, void *data)
{
char *path = NULL, filein[256], *filename = "";
char *parse;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(base);
AST_APP_ARG(filename);
);
char *mydata, *argv[2], *path = NULL, filein[256];
char dftbase[256];
char *base;
struct ast_flags flags = {0};
struct ast_filestream *fs;
struct ast_frame *f = NULL;
struct ast_module_user *u;
struct localuser *u;
int ffactor = 320 * 80,
res = 0,
argc = 0,
done = 0,
oldr = 0,
lastop = 0,
@@ -102,43 +100,35 @@ static int dictate_exec(struct ast_channel *chan, void *data)
maxlen = 0,
mode = 0;
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
snprintf(dftbase, sizeof(dftbase), "%s/dictate", ast_config_AST_SPOOL_DIR);
if (!ast_strlen_zero(data)) {
parse = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, parse);
} else
args.argc = 0;
if (!ast_strlen_zero(data) && (mydata = ast_strdupa(data))) {
argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
}
if (args.argc && !ast_strlen_zero(args.base)) {
base = args.base;
if (argc) {
base = argv[0];
} else {
base = dftbase;
}
if (args.argc > 1 && args.filename) {
filename = args.filename;
}
oldr = chan->readformat;
if ((res = ast_set_read_format(chan, AST_FORMAT_SLINEAR)) < 0) {
ast_log(LOG_WARNING, "Unable to set to linear mode.\n");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
ast_answer(chan);
ast_safe_sleep(chan, 200);
for (res = 0; !res;) {
if (ast_strlen_zero(filename)) {
if (ast_app_getdata(chan, "dictate/enter_filename", filein, sizeof(filein), 0) ||
ast_strlen_zero(filein)) {
res = -1;
break;
}
} else {
ast_copy_string(filein, filename, sizeof(filein));
filename = "";
for(res = 0; !res;) {
if (ast_app_getdata(chan, "dictate/enter_filename", filein, sizeof(filein), 0) ||
ast_strlen_zero(filein)) {
res = -1;
break;
}
mkdir(base, 0755);
len = strlen(base) + strlen(filein) + 2;
if (!path || len > maxlen) {
@@ -267,8 +257,7 @@ static int dictate_exec(struct ast_channel *chan, void *data)
if (lastop != DFLAG_PLAY) {
lastop = DFLAG_PLAY;
ast_closestream(fs);
if (!(fs = ast_openstream(chan, path, chan->language)))
break;
fs = ast_openstream(chan, path, chan->language);
ast_seekstream(fs, samples, SEEK_SET);
chan->stream = NULL;
}
@@ -330,20 +319,40 @@ static int dictate_exec(struct ast_channel *chan, void *data)
if (oldr) {
ast_set_read_format(chan, oldr);
}
ast_module_user_remove(u);
return 0;
}
static int unload_module(void)
{
int res;
res = ast_unregister_application(app);
LOCAL_USER_REMOVE(u);
return res;
}
static int load_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
int load_module(void)
{
return ast_register_application(app, dictate_exec, synopsis, desc);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Virtual Dictation Machine");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -20,20 +20,18 @@
*
* \brief Directed Call Pickup Support
*
* \author Joshua Colp <jcolp@digium.com>
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
@@ -41,141 +39,131 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/app.h"
#include "asterisk/options.h"
#define PICKUPMARK "PICKUPMARK"
static const char *tdesc = "Directed Call Pickup Application";
static const char *app = "Pickup";
static const char *synopsis = "Directed Call Pickup";
static const char *descrip =
" Pickup(extension[@context][&extension2@context...]): This application can pickup any ringing channel\n"
" Pickup(extension[@context]): This application can pickup any ringing channel\n"
"that is calling the specified extension. If no context is specified, the current\n"
"context will be used. If you use the special string \"PICKUPMARK\" for the context parameter, for example\n"
"10@PICKUPMARK, this application tries to find a channel which has defined a channel variable with the same content\n"
"as \"extension\".";
"context will be used.\n";
/* Perform actual pickup between two channels */
static int pickup_do(struct ast_channel *chan, struct ast_channel *target)
{
int res = 0;
STANDARD_LOCAL_USER;
if (option_debug)
ast_log(LOG_DEBUG, "Call pickup on '%s' by '%s'\n", target->name, chan->name);
LOCAL_USER_DECL;
if ((res = ast_answer(chan))) {
ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
return -1;
}
if ((res = ast_queue_control(chan, AST_CONTROL_ANSWER))) {
ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
return -1;
}
if ((res = ast_channel_masquerade(target, chan))) {
ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, target->name);
return -1;
}
return res;
}
/* Helper function that determines whether a channel is capable of being picked up */
static int can_pickup(struct ast_channel *chan)
{
if (!chan->pbx && (chan->_state == AST_STATE_RINGING || chan->_state == AST_STATE_RING || chan->_state == AST_STATE_DOWN))
return 1;
else
return 0;
}
/* Attempt to pick up specified extension with context */
static int pickup_by_exten(struct ast_channel *chan, char *exten, char *context)
{
int res = -1;
struct ast_channel *target = NULL;
while ((target = ast_channel_walk_locked(target))) {
if ((!strcasecmp(target->macroexten, exten) || !strcasecmp(target->exten, exten)) &&
!strcasecmp(target->dialcontext, context) &&
can_pickup(target)) {
res = pickup_do(chan, target);
ast_channel_unlock(target);
break;
}
ast_channel_unlock(target);
}
return res;
}
/* Attempt to pick up specified mark */
static int pickup_by_mark(struct ast_channel *chan, char *mark)
{
int res = -1;
const char *tmp = NULL;
struct ast_channel *target = NULL;
while ((target = ast_channel_walk_locked(target))) {
if ((tmp = pbx_builtin_getvar_helper(target, PICKUPMARK)) &&
!strcasecmp(tmp, mark) &&
can_pickup(target)) {
res = pickup_do(chan, target);
ast_channel_unlock(target);
break;
}
ast_channel_unlock(target);
}
return res;
}
/* Main application entry point */
static int pickup_exec(struct ast_channel *chan, void *data)
{
int res = 0;
struct ast_module_user *u = NULL;
char *tmp = ast_strdupa(data);
char *exten = NULL, *context = NULL;
struct localuser *u = NULL;
struct ast_channel *origin = NULL, *target = NULL;
char *tmp = NULL, *exten = NULL, *context = NULL;
char workspace[256] = "";
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Pickup requires an argument (extension)!\n");
ast_log(LOG_WARNING, "Pickup requires an argument (extension) !\n");
return -1;
}
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
/* Parse extension (and context if there) */
while (!ast_strlen_zero(tmp) && (exten = strsep(&tmp, "&"))) {
if ((context = strchr(exten, '@')))
*context++ = '\0';
if (context && !strcasecmp(context, PICKUPMARK)) {
if (!pickup_by_mark(chan, exten))
break;
} else {
if (!pickup_by_exten(chan, exten, context ? context : chan->context))
break;
}
ast_log(LOG_NOTICE, "No target channel found for %s.\n", exten);
/* Get the extension and context if present */
exten = data;
context = strchr(data, '@');
if (context) {
*context = '\0';
context++;
}
ast_module_user_remove(u);
/* Find a channel to pickup */
origin = ast_get_channel_by_exten_locked(exten, context);
if (origin && origin->cdr) {
ast_cdr_getvar(origin->cdr, "dstchannel", &tmp, workspace,
sizeof(workspace), 0);
if (tmp) {
/* We have a possible channel... now we need to find it! */
target = ast_get_channel_by_name_locked(tmp);
} else {
ast_log(LOG_DEBUG, "No target channel found.\n");
res = -1;
}
ast_mutex_unlock(&origin->lock);
} else {
if (origin)
ast_mutex_unlock(&origin->lock);
ast_log(LOG_DEBUG, "No originating channel found.\n");
}
if (res)
goto out;
if (target && (!target->pbx) && ((target->_state == AST_STATE_RINGING) || (target->_state == AST_STATE_RING))) {
ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n", target->name,
chan->name);
res = ast_answer(chan);
if (res) {
ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
res = -1;
goto out;
}
res = ast_queue_control(chan, AST_CONTROL_ANSWER);
if (res) {
ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n",
chan->name);
res = -1;
goto out;
}
res = ast_channel_masquerade(target, chan);
if (res) {
ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, target->name);
res = -1;
goto out;
}
} else {
ast_log(LOG_DEBUG, "No call pickup possible...\n");
res = -1;
}
/* Done */
out:
if (target)
ast_mutex_unlock(&target->lock);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, pickup_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Directed Call Pickup Application");
char *description(void)
{
return (char *) tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,21 +19,19 @@
/*! \file
*
* \brief Provide a directory of extensions
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
@@ -43,18 +41,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/config.h"
#include "asterisk/say.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"
#ifdef ODBC_STORAGE
#include <errno.h>
#include <sys/mman.h>
#include "asterisk/res_odbc.h"
static char odbc_database[80] = "asterisk";
static char odbc_table[80] = "voicemessages";
static char vmfmts[80] = "wav";
#endif
static char *tdesc = "Extension Directory";
static char *app = "Directory";
static char *synopsis = "Provide directory of voicemail extensions";
@@ -63,7 +51,7 @@ static char *descrip =
"the calling channel with a directory of extensions from which they can search\n"
"by name. The list of names and corresponding extensions is retrieved from the\n"
"voicemail configuration file, voicemail.conf.\n"
" This application will immediately exit if one of the following DTMF digits are\n"
" This applicaiton will immediate exit if one of the following DTMF digits are\n"
"received and the extension to jump to exists:\n"
" 0 - Jump to the 'o' extension, if it exists.\n"
" * - Jump to the 'a' extension, if it exists.\n\n"
@@ -74,10 +62,8 @@ static char *descrip =
" extension that the user has selected, or when jumping to the\n"
" 'o' or 'a' extension.\n\n"
" Options:\n"
" e - In addition to the name, also read the extension number to the\n"
" caller before presenting dialing options.\n"
" f - Allow the caller to enter the first name of a user in the directory\n"
" instead of using the last name.\n";
" instead of using the last name.\n";
/* For simplicity, I'm keeping the format compatible with the voicemail config,
but i'm open to suggestions for isolating it */
@@ -87,127 +73,15 @@ static char *descrip =
/* How many digits to read in */
#define NUMDIGITS 3
STANDARD_LOCAL_USER;
#ifdef ODBC_STORAGE
struct generic_prepare_struct {
const char *sql;
const char *param;
};
LOCAL_USER_DECL;
static SQLHSTMT generic_prepare(struct odbc_obj *obj, void *data)
{
struct generic_prepare_struct *gps = data;
SQLHSTMT stmt;
int res;
res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
return NULL;
}
res = SQLPrepare(stmt, (unsigned char *)gps->sql, SQL_NTS);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", (char *)gps->sql);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
return NULL;
}
if (!ast_strlen_zero(gps->param))
SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(gps->param), 0, (void *)gps->param, 0, NULL);
return stmt;
}
static void retrieve_file(char *dir)
{
int x = 0;
int res;
int fd=-1;
size_t fdlen = 0;
void *fdm = MAP_FAILED;
SQLHSTMT stmt;
char sql[256];
char fmt[80]="", empty[10] = "";
char *c;
SQLLEN colsize;
char full_fn[256];
struct odbc_obj *obj;
struct generic_prepare_struct gps = { .sql = sql, .param = dir };
obj = ast_odbc_request_obj(odbc_database, 1);
if (obj) {
do {
ast_copy_string(fmt, vmfmts, sizeof(fmt));
c = strchr(fmt, '|');
if (c)
*c = '\0';
if (!strcasecmp(fmt, "wav49"))
strcpy(fmt, "WAV");
snprintf(full_fn, sizeof(full_fn), "%s.%s", dir, fmt);
snprintf(sql, sizeof(sql), "SELECT recording FROM %s WHERE dir=? AND msgnum=-1", odbc_table);
stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps);
if (!stmt) {
ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
break;
}
res = SQLFetch(stmt);
if (res == SQL_NO_DATA) {
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
break;
} else if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
break;
}
fd = open(full_fn, O_RDWR | O_CREAT | O_TRUNC, 0770);
if (fd < 0) {
ast_log(LOG_WARNING, "Failed to write '%s': %s\n", full_fn, strerror(errno));
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
break;
}
res = SQLGetData(stmt, 1, SQL_BINARY, empty, 0, &colsize);
fdlen = colsize;
if (fd > -1) {
char tmp[1]="";
lseek(fd, fdlen - 1, SEEK_SET);
if (write(fd, tmp, 1) != 1) {
close(fd);
fd = -1;
break;
}
if (fd > -1)
fdm = mmap(NULL, fdlen, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
}
if (fdm != MAP_FAILED) {
memset(fdm, 0, fdlen);
res = SQLGetData(stmt, x + 1, SQL_BINARY, fdm, fdlen, &colsize);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
break;
}
}
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
} while (0);
ast_odbc_release_obj(obj);
} else
ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
if (fdm != MAP_FAILED)
munmap(fdm, fdlen);
if (fd > -1)
close(fd);
return;
}
#endif
static char *convert(const char *lastname)
static char *convert(char *lastname)
{
char *tmp;
int lcount = 0;
tmp = ast_malloc(NUMDIGITS + 1);
tmp = malloc(NUMDIGITS + 1);
if (tmp) {
while((*lastname > 32) && lcount < NUMDIGITS) {
switch(toupper(*lastname)) {
@@ -277,79 +151,80 @@ static char *convert(const char *lastname)
* '1' for selected entry from directory
* '*' for skipped entry from directory
*/
static int play_mailbox_owner(struct ast_channel *chan, char *context,
char *dialcontext, char *ext, char *name, int readext,
int fromappvm)
{
static int play_mailbox_owner(struct ast_channel *chan, char *context, char *dialcontext, char *ext, char *name) {
int res = 0;
int loop;
int loop = 3;
char fn[256];
char fn2[256];
/* Check for the VoiceMail2 greeting first */
snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/greet",
ast_config_AST_SPOOL_DIR, context, ext);
#ifdef ODBC_STORAGE
retrieve_file(fn);
#endif
(char *)ast_config_AST_SPOOL_DIR, context, ext);
if (ast_fileexists(fn, NULL, chan->language) <= 0) {
/* no file, check for an old-style Voicemail greeting */
snprintf(fn, sizeof(fn), "%s/vm/%s/greet",
ast_config_AST_SPOOL_DIR, ext);
}
#ifdef ODBC_STORAGE
retrieve_file(fn);
#endif
/* Otherwise, check for an old-style Voicemail greeting */
snprintf(fn2, sizeof(fn2), "%s/vm/%s/greet",
(char *)ast_config_AST_SPOOL_DIR, ext);
if (ast_fileexists(fn, NULL, chan->language) > 0) {
res = ast_stream_and_wait(chan, fn, chan->language, AST_DIGIT_ANY);
res = ast_streamfile(chan, fn, chan->language);
if (!res) {
res = ast_waitstream(chan, AST_DIGIT_ANY);
}
ast_stopstream(chan);
/* If Option 'e' was specified, also read the extension number with the name */
if (readext) {
ast_stream_and_wait(chan, "vm-extension", chan->language, AST_DIGIT_ANY);
res = ast_say_character_str(chan, ext, AST_DIGIT_ANY, chan->language);
} else if (ast_fileexists(fn2, NULL, chan->language) > 0) {
res = ast_streamfile(chan, fn2, chan->language);
if (!res) {
res = ast_waitstream(chan, AST_DIGIT_ANY);
}
ast_stopstream(chan);
} else {
res = ast_say_character_str(chan, S_OR(name, ext), AST_DIGIT_ANY, chan->language);
if (!ast_strlen_zero(name) && readext) {
ast_stream_and_wait(chan, "vm-extension", chan->language, AST_DIGIT_ANY);
res = ast_say_character_str(chan, ext, AST_DIGIT_ANY, chan->language);
}
res = ast_say_character_str(chan, !ast_strlen_zero(name) ? name : ext,
AST_DIGIT_ANY, chan->language);
}
#ifdef ODBC_STORAGE
ast_filedelete(fn, NULL);
#endif
for (loop = 3 ; loop > 0; loop--) {
if (!res)
res = ast_stream_and_wait(chan, "dir-instr", chan->language, AST_DIGIT_ANY);
if (!res)
while (loop) {
if (!res) {
res = ast_streamfile(chan, "dir-instr", chan->language);
}
if (!res) {
res = ast_waitstream(chan, AST_DIGIT_ANY);
}
if (!res) {
res = ast_waitfordigit(chan, 3000);
}
ast_stopstream(chan);
if (res < 0) /* User hungup, so jump out now */
break;
if (res == '1') { /* Name selected */
if (fromappvm) {
/* We still want to set the exten though */
ast_copy_string(chan->exten, ext, sizeof(chan->exten));
} else {
if (ast_goto_if_exists(chan, dialcontext, ext, 1)) {
ast_log(LOG_WARNING,
"Can't find extension '%s' in context '%s'. "
"Did you pass the wrong context to Directory?\n",
ext, dialcontext);
res = -1;
}
}
break;
if (res > -1) {
switch (res) {
case '1':
/* Name selected */
loop = 0;
if (ast_goto_if_exists(chan, dialcontext, ext, 1)) {
ast_log(LOG_WARNING,
"Can't find extension '%s' in context '%s'. "
"Did you pass the wrong context to Directory?\n",
ext, dialcontext);
res = -1;
}
break;
case '*':
/* Skip to next match in list */
loop = 0;
break;
default:
/* Not '1', or '*', so decrement number of tries */
res = 0;
loop--;
break;
} /* end switch */
} /* end if */
else {
/* User hungup, so jump out now */
loop = 0;
}
if (res == '*') /* Skip to next match in list */
break;
/* Not '1', or '*', so decrement number of tries */
res = 0;
}
} /* end while */
return(res);
}
@@ -361,8 +236,8 @@ static struct ast_config *realtime_directory(char *context)
struct ast_category *cat;
struct ast_variable *var;
char *mailbox;
const char *fullname;
const char *hidefromdir;
char *fullname;
char *hidefromdir;
char tmp[100];
/* Load flat file config. */
@@ -389,16 +264,13 @@ static struct ast_config *realtime_directory(char *context)
if (!cat) {
ast_log(LOG_WARNING, "Out of memory\n");
ast_config_destroy(cfg);
if (rtdata) {
ast_config_destroy(rtdata);
}
return NULL;
}
ast_category_append(cfg, cat);
}
mailbox = NULL;
while ( (mailbox = ast_category_browse(rtdata, mailbox)) ) {
mailbox = ast_category_browse(rtdata, NULL);
while (mailbox) {
fullname = ast_variable_retrieve(rtdata, mailbox, "fullname");
hidefromdir = ast_variable_retrieve(rtdata, mailbox, "hidefromdir");
snprintf(tmp, sizeof(tmp), "no-password,%s,hidefromdir=%s",
@@ -409,24 +281,23 @@ static struct ast_config *realtime_directory(char *context)
ast_variable_append(cat, var);
else
ast_log(LOG_WARNING, "Out of memory adding mailbox '%s'\n", mailbox);
mailbox = ast_category_browse(rtdata, mailbox);
}
ast_config_destroy(rtdata);
return cfg;
}
static int do_directory(struct ast_channel *chan, struct ast_config *cfg, struct ast_config *ucfg, char *context, char *dialcontext, char digit, int last, int readext, int fromappvm)
static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *context, char *dialcontext, char digit, int last)
{
/* Read in the first three digits.. "digit" is the first digit, already read */
char ext[NUMDIGITS + 1], *cat;
char ext[NUMDIGITS + 1];
char name[80] = "";
struct ast_variable *v;
int res;
int found=0;
int lastuserchoice = 0;
char *start, *conv, *stringp = NULL;
const char *pos;
int breakout = 0;
char *start, *pos, *conv,*stringp=NULL;
if (ast_strlen_zero(context)) {
ast_log(LOG_WARNING,
@@ -435,7 +306,7 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, struct
return -1;
}
if (digit == '0') {
if (!ast_goto_if_exists(chan, dialcontext, "o", 1) ||
if (!ast_goto_if_exists(chan, chan->context, "o", 1) ||
(!ast_strlen_zero(chan->macrocontext) &&
!ast_goto_if_exists(chan, chan->macrocontext, "o", 1))) {
return 0;
@@ -446,7 +317,7 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, struct
}
}
if (digit == '*') {
if (!ast_goto_if_exists(chan, dialcontext, "a", 1) ||
if (!ast_goto_if_exists(chan, chan->context, "a", 1) ||
(!ast_strlen_zero(chan->macrocontext) &&
!ast_goto_if_exists(chan, chan->macrocontext, "a", 1))) {
return 0;
@@ -479,7 +350,7 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, struct
pos = strrchr(pos, ' ') + 1;
conv = convert(pos);
if (conv) {
if (!strncmp(conv, ext, strlen(ext))) {
if (!strcmp(conv, ext)) {
/* Match! */
found++;
free(conv);
@@ -496,7 +367,7 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, struct
if (v) {
/* We have a match -- play a greeting if they have it */
res = play_mailbox_owner(chan, context, dialcontext, v->name, name, readext, fromappvm);
res = play_mailbox_owner(chan, context, dialcontext, v->name, name);
switch (res) {
case -1:
/* user pressed '1' but extension does not exist, or
@@ -523,66 +394,11 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, struct
}
}
if (!res && ucfg) {
/* Search users.conf for all names which start with those digits */
for (cat = ast_category_browse(ucfg, NULL); cat && !res ; cat = ast_category_browse(ucfg, cat)) {
if (!strcasecmp(cat, "general"))
continue;
if (!ast_true(ast_config_option(ucfg, cat, "hasdirectory")))
continue;
/* Find all candidate extensions */
if ((pos = ast_variable_retrieve(ucfg, cat, "fullname"))) {
ast_copy_string(name, pos, sizeof(name));
/* Grab the last name */
if (last && strrchr(pos,' '))
pos = strrchr(pos, ' ') + 1;
conv = convert(pos);
if (conv) {
if (!strcmp(conv, ext)) {
/* Match! */
found++;
/* We have a match -- play a greeting if they have it */
res = play_mailbox_owner(chan, context, dialcontext, cat, name, readext, fromappvm);
switch (res) {
case -1:
/* user pressed '1' but extension does not exist, or
* user hungup
*/
lastuserchoice = 0;
breakout = 1;
break;
case '1':
/* user pressed '1' and extensions exists;
play_mailbox_owner will already have done
a goto() on the channel
*/
lastuserchoice = res;
breakout = 1;
break;
case '*':
/* user pressed '*' to skip something found */
lastuserchoice = res;
breakout = 0;
res = 0;
break;
default:
breakout = 1;
break;
}
free(conv);
if (breakout)
break;
}
else
free(conv);
}
}
}
}
if (lastuserchoice != '1') {
res = ast_streamfile(chan, found ? "dir-nomore" : "dir-nomatch", chan->language);
if (found)
res = ast_streamfile(chan, "dir-nomore", chan->language);
else
res = ast_streamfile(chan, "dir-nomatch", chan->language);
if (!res)
res = 1;
return res;
@@ -595,113 +411,106 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, struct
static int directory_exec(struct ast_channel *chan, void *data)
{
int res = 0;
struct ast_module_user *u;
struct ast_config *cfg, *ucfg;
struct localuser *u;
struct ast_config *cfg;
int last = 1;
int readext = 0;
int fromappvm = 0;
const char *dirintro;
char *parse;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(vmcontext);
AST_APP_ARG(dialcontext);
AST_APP_ARG(options);
);
char *context, *dialcontext, *dirintro, *options;
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Directory requires an argument (context[,dialcontext])\n");
return -1;
}
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
parse = ast_strdupa(data);
context = ast_strdupa(data);
dialcontext = strchr(context, '|');
if (dialcontext) {
*dialcontext = '\0';
dialcontext++;
options = strchr(dialcontext, '|');
if (options) {
*options = '\0';
options++;
if (strchr(options, 'f'))
last = 0;
}
} else
dialcontext = context;
AST_STANDARD_APP_ARGS(args, parse);
if (args.options) {
if (strchr(args.options, 'f'))
last = 0;
if (strchr(args.options, 'e'))
readext = 1;
if (strchr(args.options, 'v'))
fromappvm = 1;
}
if (ast_strlen_zero(args.dialcontext))
args.dialcontext = args.vmcontext;
cfg = realtime_directory(args.vmcontext);
cfg = realtime_directory(context);
if (!cfg) {
ast_log(LOG_ERROR, "Unable to read the configuration data!\n");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
ucfg = ast_config_load("users.conf");
dirintro = ast_variable_retrieve(cfg, args.vmcontext, "directoryintro");
dirintro = ast_variable_retrieve(cfg, context, "directoryintro");
if (ast_strlen_zero(dirintro))
dirintro = ast_variable_retrieve(cfg, "general", "directoryintro");
if (ast_strlen_zero(dirintro))
dirintro = last ? "dir-intro" : "dir-intro-fn";
if (ast_strlen_zero(dirintro)) {
if (last)
dirintro = "dir-intro";
else
dirintro = "dir-intro-fn";
}
if (chan->_state != AST_STATE_UP)
res = ast_answer(chan);
for (;;) {
if (!res)
res = ast_stream_and_wait(chan, dirintro, chan->language, AST_DIGIT_ANY);
res = ast_streamfile(chan, dirintro, chan->language);
if (!res)
res = ast_waitstream(chan, AST_DIGIT_ANY);
ast_stopstream(chan);
if (!res)
res = ast_waitfordigit(chan, 5000);
if (res > 0) {
res = do_directory(chan, cfg, ucfg, args.vmcontext, args.dialcontext, res, last, readext, fromappvm);
res = do_directory(chan, cfg, context, dialcontext, res, last);
if (res > 0) {
res = ast_waitstream(chan, AST_DIGIT_ANY);
ast_stopstream(chan);
if (res >= 0)
if (res >= 0) {
continue;
}
}
}
break;
}
if (ucfg)
ast_config_destroy(ucfg);
ast_config_destroy(cfg);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
#ifdef ODBC_STORAGE
struct ast_config *cfg = ast_config_load(VOICEMAIL_CONFIG);
const char *tmp;
if (cfg) {
if ((tmp = ast_variable_retrieve(cfg, "general", "odbcstorage"))) {
ast_copy_string(odbc_database, tmp, sizeof(odbc_database));
}
if ((tmp = ast_variable_retrieve(cfg, "general", "odbctable"))) {
ast_copy_string(odbc_table, tmp, sizeof(odbc_table));
}
if ((tmp = ast_variable_retrieve(cfg, "general", "format"))) {
ast_copy_string(vmfmts, tmp, sizeof(vmfmts));
}
ast_config_destroy(cfg);
} else
ast_log(LOG_WARNING, "Unable to load " VOICEMAIL_CONFIG " - ODBC defaults will be used\n");
#endif
return ast_register_application(app, directory_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Extension Directory");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -26,16 +26,16 @@
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <sys/time.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
@@ -47,14 +47,15 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/translate.h"
#include "asterisk/ulaw.h"
#include "asterisk/callerid.h"
#include "asterisk/stringfields.h"
static char *tdesc = "DISA (Direct Inward System Access) Application";
static char *app = "DISA";
static char *synopsis = "DISA (Direct Inward System Access)";
static char *descrip =
"DISA(<numeric passcode>[|<context>]) or DISA(<filename>)\n"
"DISA(<numeric passcode>[|<context>]) or disa(<filename>)\n"
"The DISA, Direct Inward System Access, application allows someone from \n"
"outside the telephone switch (PBX) to obtain an \"internal\" system \n"
"dialtone and to place calls from it as if they were placing a call from \n"
@@ -70,7 +71,7 @@ static char *descrip =
"Be aware that using this compromises the security of your PBX.\n\n"
"The arguments to this application (in extensions.conf) allow either\n"
"specification of a single global passcode (that everyone uses), or\n"
"individual passcodes contained in a file. It also allows specification\n"
"individual passcodes contained in a file. It also allow specification\n"
"of the context on which the user will be dialing. If no context is\n"
"specified, the DISA application defaults the context to \"disa\".\n"
"Presumably a normal system will have a special context set up\n"
@@ -92,9 +93,11 @@ static char *descrip =
"If login is successful, the application looks up the dialed number in\n"
"the specified (or default) context, and executes it if found.\n"
"If the user enters an invalid extension and extension \"i\" (invalid) \n"
"exists in the context, it will be used. Also, if you set the 5th argument\n"
"to 'NOANSWER', the DISA application will not answer initially.\n";
"exists in the context, it will be used.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static void play_dialtone(struct ast_channel *chan, char *mailbox)
{
@@ -111,10 +114,10 @@ static void play_dialtone(struct ast_channel *chan, char *mailbox)
static int disa_exec(struct ast_channel *chan, void *data)
{
int i,j,k,x,did_ignore,special_noanswer;
int i,j,k,x,did_ignore;
int firstdigittimeout = 20000;
int digittimeout = 10000;
struct ast_module_user *u;
struct localuser *u;
char *tmp, exten[AST_MAX_EXTENSION],acctcode[20]="";
char pwline[256];
char ourcidname[256],ourcidnum[256];
@@ -128,15 +131,14 @@ static int disa_exec(struct ast_channel *chan, void *data)
AST_APP_ARG(context);
AST_APP_ARG(cid);
AST_APP_ARG(mailbox);
AST_APP_ARG(noanswer);
);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "DISA requires an argument (passcode/passcode file)\n");
ast_log(LOG_WARNING, "disa requires an argument (passcode/passcode file)\n");
return -1;
}
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
if (chan->pbx) {
firstdigittimeout = chan->pbx->rtimeout*1000;
@@ -144,13 +146,13 @@ static int disa_exec(struct ast_channel *chan, void *data)
}
if (ast_set_write_format(chan,AST_FORMAT_ULAW)) {
ast_log(LOG_WARNING, "Unable to set write format to Mu-law on %s\n", chan->name);
ast_module_user_remove(u);
ast_log(LOG_WARNING, "Unable to set write format to Mu-law on %s\n",chan->name);
LOCAL_USER_REMOVE(u);
return -1;
}
if (ast_set_read_format(chan,AST_FORMAT_ULAW)) {
ast_log(LOG_WARNING, "Unable to set read format to Mu-law on %s\n", chan->name);
ast_module_user_remove(u);
ast_log(LOG_WARNING, "Unable to set read format to Mu-law on %s\n",chan->name);
LOCAL_USER_REMOVE(u);
return -1;
}
@@ -158,6 +160,11 @@ static int disa_exec(struct ast_channel *chan, void *data)
ast_log(LOG_DEBUG, "Responsetimeout: %d\n", firstdigittimeout);
tmp = ast_strdupa(data);
if (!tmp) {
ast_log(LOG_ERROR, "Out of memory\n");
LOCAL_USER_REMOVE(u);
return -1;
}
AST_STANDARD_APP_ARGS(args, tmp);
@@ -168,15 +175,10 @@ static int disa_exec(struct ast_channel *chan, void *data)
ast_log(LOG_DEBUG, "Mailbox: %s\n",args.mailbox);
special_noanswer = 0;
if ((!args.noanswer) || strcmp(args.noanswer,"NOANSWER"))
{
if (chan->_state != AST_STATE_UP) {
/* answer */
ast_answer(chan);
}
} else special_noanswer = 1;
if (chan->_state != AST_STATE_UP) {
/* answer */
ast_answer(chan);
}
i = k = x = 0; /* k is 0 for pswd entry, 1 for ext entry */
did_ignore = 0;
exten[0] = 0;
@@ -196,7 +198,8 @@ static int disa_exec(struct ast_channel *chan, void *data)
for (;;) {
/* if outa time, give em reorder */
if (ast_tvdiff_ms(ast_tvnow(), lastdigittime) >
((k&2) ? digittimeout : firstdigittimeout)) {
((k&2) ? digittimeout : firstdigittimeout))
{
ast_log(LOG_DEBUG,"DISA %s entry timeout on chan %s\n",
((k&1) ? "extension" : "password"),chan->name);
break;
@@ -207,68 +210,72 @@ static int disa_exec(struct ast_channel *chan, void *data)
}
f = ast_read(chan);
if (f == NULL) {
ast_module_user_remove(u);
if (f == NULL)
{
LOCAL_USER_REMOVE(u);
return -1;
}
if ((f->frametype == AST_FRAME_CONTROL) &&
(f->subclass == AST_CONTROL_HANGUP)) {
(f->subclass == AST_CONTROL_HANGUP))
{
ast_frfree(f);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
if (f->frametype == AST_FRAME_VOICE) {
ast_frfree(f);
continue;
}
/* if not DTMF, just do it again */
if (f->frametype != AST_FRAME_DTMF) {
/* if not DTMF, just do it again */
if (f->frametype != AST_FRAME_DTMF)
{
ast_frfree(f);
continue;
}
j = f->subclass; /* save digit */
ast_frfree(f);
if (i == 0) {
if (i == 0)
{
k|=2; /* We have the first digit */
ast_playtones_stop(chan);
}
lastdigittime = ast_tvnow();
/* got a DTMF tone */
if (i < AST_MAX_EXTENSION) { /* if still valid number of digits */
if (!(k&1)) { /* if in password state */
if (j == '#') { /* end of password */
if (i < AST_MAX_EXTENSION) /* if still valid number of digits */
{
if (!(k&1)) /* if in password state */
{
if (j == '#') /* end of password */
{
/* see if this is an integer */
if (sscanf(args.passcode,"%d",&j) < 1) { /* nope, it must be a filename */
if (sscanf(args.passcode,"%d",&j) < 1)
{ /* nope, it must be a filename */
fp = fopen(args.passcode,"r");
if (!fp) {
if (!fp)
{
ast_log(LOG_WARNING,"DISA password file %s not found on chan %s\n",args.passcode,chan->name);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
}
pwline[0] = 0;
while(fgets(pwline,sizeof(pwline) - 1,fp)) {
if (!pwline[0])
continue;
while(fgets(pwline,sizeof(pwline) - 1,fp))
{
if (!pwline[0]) continue;
if (pwline[strlen(pwline) - 1] == '\n')
pwline[strlen(pwline) - 1] = 0;
if (!pwline[0])
continue;
/* skip comments */
if (pwline[0] == '#')
continue;
if (pwline[0] == ';')
continue;
if (!pwline[0]) continue;
/* skip comments */
if (pwline[0] == '#') continue;
if (pwline[0] == ';') continue;
AST_STANDARD_APP_ARGS(args, pwline);
ast_log(LOG_DEBUG, "Mailbox: %s\n",args.mailbox);
/* password must be in valid format (numeric) */
if (sscanf(args.passcode,"%d", &j) < 1)
continue;
/* if we got it */
/* password must be in valid format (numeric) */
if (sscanf(args.passcode,"%d",&j) < 1) continue;
/* if we got it */
if (!strcmp(exten,args.passcode)) {
if (ast_strlen_zero(args.context))
args.context = "disa";
@@ -276,11 +283,12 @@ static int disa_exec(struct ast_channel *chan, void *data)
args.mailbox = "";
break;
}
}
}
fclose(fp);
}
/* compare the two */
if (strcmp(exten,args.passcode)) {
}
/* compare the two */
if (strcmp(exten,args.passcode))
{
ast_log(LOG_WARNING,"DISA on chan %s got bad password %s\n",chan->name,exten);
goto reorder;
@@ -294,26 +302,15 @@ static int disa_exec(struct ast_channel *chan, void *data)
exten[sizeof(acctcode)] = 0;
ast_copy_string(acctcode, exten, sizeof(acctcode));
exten[0] = 0;
ast_log(LOG_DEBUG,"Successful DISA log-in on chan %s\n", chan->name);
ast_log(LOG_DEBUG,"Successful DISA log-in on chan %s\n",chan->name);
continue;
}
} else {
if (j == '#') { /* end of extension .. maybe */
if (i == 0 &&
(ast_matchmore_extension(chan, args.context, "#", 1, chan->cid.cid_num) ||
ast_exists_extension(chan, args.context, "#", 1, chan->cid.cid_num)) ) {
/* Let the # be the part of, or the entire extension */
} else {
break;
}
}
}
exten[i++] = j; /* save digit */
exten[i] = 0;
if (!(k&1))
continue; /* if getting password, continue doing it */
/* if this exists */
if (!(k&1)) continue; /* if getting password, continue doing it */
/* if this exists */
if (ast_ignore_pattern(args.context, exten)) {
play_dialtone(chan, "");
@@ -324,7 +321,7 @@ static int disa_exec(struct ast_channel *chan, void *data)
did_ignore = 0;
}
/* if can do some more, do it */
/* if can do some more, do it */
if (!ast_matchmore_extension(chan,args.context,exten,1, chan->cid.cid_num)) {
break;
}
@@ -344,18 +341,18 @@ static int disa_exec(struct ast_channel *chan, void *data)
if (!recheck || ast_exists_extension(chan, args.context, exten, 1, chan->cid.cid_num)) {
ast_playtones_stop(chan);
/* We're authenticated and have a target extension */
if (!ast_strlen_zero(args.cid)) {
if (!ast_strlen_zero(args.cid))
{
ast_callerid_split(args.cid, ourcidname, sizeof(ourcidname), ourcidnum, sizeof(ourcidnum));
ast_set_callerid(chan, ourcidnum, ourcidname, ourcidnum);
}
if (!ast_strlen_zero(acctcode))
ast_string_field_set(chan, accountcode, acctcode);
ast_copy_string(chan->accountcode, acctcode, sizeof(chan->accountcode));
if (special_noanswer) flags.flags = 0;
ast_cdr_reset(chan->cdr, &flags);
ast_explicit_goto(chan, args.context, exten, 1);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return 0;
}
}
@@ -367,7 +364,8 @@ reorder:
ast_indicate(chan,AST_CONTROL_CONGESTION);
/* something is invalid, give em reorder for several seconds */
time(&rstart);
while(time(NULL) < rstart + 10) {
while(time(NULL) < rstart + 10)
{
if (ast_waitfor(chan, -1) < 0)
break;
f = ast_read(chan);
@@ -376,24 +374,39 @@ reorder:
ast_frfree(f);
}
ast_playtones_stop(chan);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, disa_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "DISA (Direct Inward System Access) Application");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key(void)
{
return ASTERISK_GPL_KEY;
}

View File

@@ -5,8 +5,7 @@
*
* Anthony Minessale <anthmct@yahoo.com>
*
* A license has been granted to Digium (via disclaimer) for the use of
* this code.
* disclaimed to Digium
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
@@ -22,21 +21,19 @@
/*! \file
*
* \brief Application to dump channel variables
*
* \author Anthony Minessale <anthmct@yahoo.com>
*
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
@@ -47,27 +44,30 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/utils.h"
static char *tdesc = "Dump Info About The Calling Channel";
static char *app = "DumpChan";
static char *synopsis = "Dump Info About The Calling Channel";
static char *desc =
" DumpChan([<min_verbose_level>])\n"
"Displays information on channel and listing of all channel\n"
"variables. If min_verbose_level is specified, output is only\n"
"displayed when the verbose level is currently set to that number\n"
"or greater. \n";
" DumpChan([<min_verbose_level>])\n"
"Displays information on channel and listing of all channel\n"
"variables. If min_verbose_level is specified, output is only\n"
"displayed when the verbose level is currently set to that number\n"
"or greater. \n";
STANDARD_LOCAL_USER;
static int serialize_showchan(struct ast_channel *c, char *buf, size_t size)
LOCAL_USER_DECL;
static int ast_serialize_showchan(struct ast_channel *c, char *buf, size_t size)
{
struct timeval now;
long elapsed_seconds = 0;
int hour = 0, min = 0, sec = 0;
char cgrp[BUFSIZ/2];
char pgrp[BUFSIZ/2];
char formatbuf[BUFSIZ/2];
long elapsed_seconds=0;
int hour=0, min=0, sec=0;
char cgrp[256];
char pgrp[256];
now = ast_tvnow();
memset(buf, 0, size);
memset(buf,0,size);
if (!c)
return 0;
@@ -85,12 +85,11 @@ static int serialize_showchan(struct ast_channel *c, char *buf, size_t size)
"CallerID= %s\n"
"CallerIDName= %s\n"
"DNIDDigits= %s\n"
"RDNIS= %s\n"
"State= %s (%d)\n"
"Rings= %d\n"
"NativeFormat= %s\n"
"WriteFormat= %s\n"
"ReadFormat= %s\n"
"NativeFormat= %d\n"
"WriteFormat= %d\n"
"ReadFormat= %d\n"
"1stFileDescriptor= %d\n"
"Framesin= %d %s\n"
"Framesout= %d %s\n"
@@ -105,20 +104,19 @@ static int serialize_showchan(struct ast_channel *c, char *buf, size_t size)
"Data= %s\n"
"Blocking_in= %s\n",
c->name,
c->tech->type,
c->type,
c->uniqueid,
S_OR(c->cid.cid_num, "(N/A)"),
S_OR(c->cid.cid_name, "(N/A)"),
S_OR(c->cid.cid_dnid, "(N/A)"),
S_OR(c->cid.cid_rdnis, "(N/A)"),
(c->cid.cid_num ? c->cid.cid_num : "(N/A)"),
(c->cid.cid_name ? c->cid.cid_name : "(N/A)"),
(c->cid.cid_dnid ? c->cid.cid_dnid : "(N/A)" ),
ast_state2str(c->_state),
c->_state,
c->rings,
ast_getformatname_multiple(formatbuf, sizeof(formatbuf), c->nativeformats),
ast_getformatname_multiple(formatbuf, sizeof(formatbuf), c->writeformat),
ast_getformatname_multiple(formatbuf, sizeof(formatbuf), c->readformat),
c->fds[0], c->fin & ~DEBUGCHAN_FLAG, (c->fin & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "",
c->fout & ~DEBUGCHAN_FLAG, (c->fout & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "", (long)c->whentohangup,
c->nativeformats,
c->writeformat,
c->readformat,
c->fds[0], c->fin & 0x7fffffff, (c->fin & 0x80000000) ? " (DEBUGGED)" : "",
c->fout & 0x7fffffff, (c->fout & 0x80000000) ? " (DEBUGGED)" : "", (long)c->whentohangup,
hour,
min,
sec,
@@ -128,7 +126,7 @@ static int serialize_showchan(struct ast_channel *c, char *buf, size_t size)
ast_print_group(cgrp, sizeof(cgrp), c->callgroup),
ast_print_group(pgrp, sizeof(pgrp), c->pickupgroup),
( c->appl ? c->appl : "(N/A)" ),
( c-> data ? S_OR(c->data, "(Empty)") : "(None)"),
( c-> data ? (!ast_strlen_zero(c->data) ? c->data : "(Empty)") : "(None)"),
(ast_test_flag(c, AST_FLAG_BLOCKING) ? c->blockproc : "(Not Blocking)"));
return 0;
@@ -136,41 +134,59 @@ static int serialize_showchan(struct ast_channel *c, char *buf, size_t size)
static int dumpchan_exec(struct ast_channel *chan, void *data)
{
struct ast_module_user *u;
char vars[BUFSIZ * 4];
int res=0;
struct localuser *u;
char vars[1024];
char info[1024];
int level = 0;
static char *line = "================================================================================";
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
if (!ast_strlen_zero(data))
if (!ast_strlen_zero(data)) {
level = atoi(data);
}
pbx_builtin_serialize_variables(chan, vars, sizeof(vars));
serialize_showchan(chan, info, sizeof(info));
ast_serialize_showchan(chan, info, sizeof(info));
if (option_verbose >= level)
ast_verbose("\nDumping Info For Channel: %s:\n%s\nInfo:\n%s\nVariables:\n%s%s\n", chan->name, line, info, vars, line);
ast_verbose("\nDumping Info For Channel: %s:\n%s\nInfo:\n%s\nVariables:\n%s%s\n",chan->name, line, info, vars, line);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return 0;
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, dumpchan_exec, synopsis, desc);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Dump Info About The Calling Channel");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,21 +19,19 @@
/*! \file
*
* \brief Echo application -- play back what you hear to evaluate latency
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
@@ -41,64 +39,85 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/pbx.h"
#include "asterisk/module.h"
static char *tdesc = "Simple Echo Application";
static char *app = "Echo";
static char *synopsis = "Echo audio, video, or DTMF back to the calling party";
static char *synopsis = "Echo audio read back to the user";
static char *descrip =
" Echo(): This application will echo any audio, video, or DTMF frames read from\n"
"the calling channel back to itself. If the DTMF digit '#' is received, the\n"
"application will exit.\n";
" Echo(): Echo audio read from channel back to the channel. \n"
"User can exit the application by either pressing the '#' key, \n"
"or hanging up.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int echo_exec(struct ast_channel *chan, void *data)
{
int res = -1;
int format;
struct ast_module_user *u;
u = ast_module_user_add(chan);
format = ast_best_codec(chan->nativeformats);
ast_set_write_format(chan, format);
ast_set_read_format(chan, format);
while (ast_waitfor(chan, -1) > -1) {
struct ast_frame *f = ast_read(chan);
int res=-1;
struct localuser *u;
struct ast_frame *f;
LOCAL_USER_ADD(u);
ast_set_write_format(chan, ast_best_codec(chan->nativeformats));
ast_set_read_format(chan, ast_best_codec(chan->nativeformats));
/* Do our thing here */
while(ast_waitfor(chan, -1) > -1) {
f = ast_read(chan);
if (!f)
break;
f->delivery.tv_sec = 0;
f->delivery.tv_usec = 0;
if (ast_write(chan, f)) {
ast_frfree(f);
goto end;
}
if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#')) {
res = 0;
ast_frfree(f);
goto end;
if (f->frametype == AST_FRAME_VOICE) {
if (ast_write(chan, f))
break;
} else if (f->frametype == AST_FRAME_VIDEO) {
if (ast_write(chan, f))
break;
} else if (f->frametype == AST_FRAME_DTMF) {
if (f->subclass == '#') {
res = 0;
break;
} else
if (ast_write(chan, f))
break;
}
ast_frfree(f);
}
end:
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, echo_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Simple Echo Application");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

270
apps/app_enumlookup.c Normal file
View File

@@ -0,0 +1,270 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2005, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief Enumlookup - lookup entry in ENUM
*
* \ingroup applications
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/enum.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"
#include "asterisk/options.h"
static char *tdesc = "ENUM Lookup";
static char *app = "EnumLookup";
static char *synopsis = "Lookup number in ENUM";
static char *descrip =
" EnumLookup(exten[|option]): Looks up an extension via ENUM and sets\n"
"the variable 'ENUM'. For VoIP URIs this variable will \n"
"look like 'TECHNOLOGY/URI' with the appropriate technology.\n"
"Currently, the enumservices SIP, H323, IAX, IAX2 and TEL are recognized. \n"
"\nReturns status in the ENUMSTATUS channel variable:\n"
" ERROR Failed to do a lookup\n"
" <tech> Technology of the successful lookup: SIP, H323, IAX, IAX2 or TEL\n"
" BADURI Got URI Asterisk does not understand.\n"
" The option string may contain zero or the following character:\n"
" 'j' -- jump to +101 priority if the lookup isn't successful.\n"
" and jump to +51 priority on a TEL entry.\n";
#define ENUM_CONFIG "enum.conf"
static char h323driver[80] = "";
#define H323DRIVERDEFAULT "H323"
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
/*--- enumlookup_exec: Look up number in ENUM and return result */
static int enumlookup_exec(struct ast_channel *chan, void *data)
{
int res=0,priority_jump=0;
char tech[80];
char dest[80];
char tmp[256];
char *c,*t = NULL;
static int dep_warning=0;
struct localuser *u;
char *parse;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(d);
AST_APP_ARG(o);
);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "EnumLookup requires an argument (extension)\n");
return -1;
}
if (!dep_warning) {
ast_log(LOG_WARNING, "The application EnumLookup is deprecated. Please use the ENUMLOOKUP() function instead.\n");
dep_warning = 1;
}
LOCAL_USER_ADD(u);
parse = ast_strdupa(data);
if (!parse) {
ast_log(LOG_ERROR, "Out of memory!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
AST_STANDARD_APP_ARGS(args, parse);
tech[0] = '\0';
dest[0] = '\0';
if (args.o) {
if (strchr(args.o, 'j'))
priority_jump = 1;
}
res = ast_get_enum(chan, args.d, dest, sizeof(dest), tech, sizeof(tech), NULL, NULL);
if (!res) { /* Failed to do a lookup */
if (priority_jump || option_priority_jumping) {
/* Look for a "busy" place */
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
}
pbx_builtin_setvar_helper(chan, "ENUMSTATUS", "ERROR");
LOCAL_USER_REMOVE(u);
return 0;
}
pbx_builtin_setvar_helper(chan, "ENUMSTATUS", tech);
/* Parse it out */
if (res > 0) {
if (!strcasecmp(tech, "SIP")) {
c = dest;
if (!strncmp(c, "sip:", 4))
c += 4;
snprintf(tmp, sizeof(tmp), "SIP/%s", c);
pbx_builtin_setvar_helper(chan, "ENUM", tmp);
} else if (!strcasecmp(tech, "h323")) {
c = dest;
if (!strncmp(c, "h323:", 5))
c += 5;
snprintf(tmp, sizeof(tmp), "%s/%s", h323driver, c);
/* do a s!;.*!! on the H323 URI */
t = strchr(c,';');
if (t)
*t = 0;
pbx_builtin_setvar_helper(chan, "ENUM", tmp);
} else if (!strcasecmp(tech, "iax")) {
c = dest;
if (!strncmp(c, "iax:", 4))
c += 4;
snprintf(tmp, sizeof(tmp), "IAX/%s", c);
pbx_builtin_setvar_helper(chan, "ENUM", tmp);
} else if (!strcasecmp(tech, "iax2")) {
c = dest;
if (!strncmp(c, "iax2:", 5))
c += 5;
snprintf(tmp, sizeof(tmp), "IAX2/%s", c);
pbx_builtin_setvar_helper(chan, "ENUM", tmp);
} else if (!strcasecmp(tech, "tel")) {
c = dest;
if (!strncmp(c, "tel:", 4))
c += 4;
if (c[0] != '+') {
ast_log(LOG_NOTICE, "tel: uri must start with a \"+\" (got '%s')\n", c);
res = 0;
} else {
/* now copy over the number, skipping all non-digits and stop at ; or NULL */
t = tmp;
while( *c && (*c != ';') && (t - tmp < (sizeof(tmp) - 1))) {
if (isdigit(*c))
*t++ = *c;
c++;
}
*t = 0;
pbx_builtin_setvar_helper(chan, "ENUM", tmp);
ast_log(LOG_NOTICE, "tel: ENUM set to \"%s\"\n", tmp);
if (priority_jump || option_priority_jumping) {
if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 51))
res = 0;
}
}
} else if (!ast_strlen_zero(tech)) {
ast_log(LOG_NOTICE, "Don't know how to handle technology '%s'\n", tech);
pbx_builtin_setvar_helper(chan, "ENUMSTATUS", "BADURI");
res = 0;
}
}
LOCAL_USER_REMOVE(u);
return 0;
}
/*--- load_config: Load enum.conf and find out how to handle H.323 */
static int load_config(void)
{
struct ast_config *cfg;
char *s;
cfg = ast_config_load(ENUM_CONFIG);
if (cfg) {
if (!(s=ast_variable_retrieve(cfg, "general", "h323driver"))) {
strncpy(h323driver, H323DRIVERDEFAULT, sizeof(h323driver) - 1);
} else {
strncpy(h323driver, s, sizeof(h323driver) - 1);
}
ast_config_destroy(cfg);
return 0;
}
ast_log(LOG_NOTICE, "No ENUM Config file, using defaults\n");
return 0;
}
/*--- unload_module: Unload this application from PBX */
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
/*--- load_module: Load this application into PBX */
int load_module(void)
{
int res;
res = ast_register_application(app, enumlookup_exec, synopsis, descrip);
if (!res)
res = load_config();
return res;
}
/*--- reload: Reload configuration file */
int reload(void)
{
return load_config();
}
/*--- description: Describe module */
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

127
apps/app_eval.c Normal file
View File

@@ -0,0 +1,127 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (c) 2004 - 2005, Tilghman Lesher. All rights reserved.
*
* Tilghman Lesher <app_eval__v001@the-tilghman.com>
*
* This code is released by the author with no restrictions on usage.
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
*/
/*! \file
* \brief Eval application
*
* \author Tilghman Lesher <app_eval__v001@the-tilghman.com>
*
* \ingroup applications
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
/* Maximum length of any variable */
#define MAXRESULT 1024
static char *tdesc = "Reevaluates strings";
static char *app_eval = "Eval";
static char *eval_synopsis = "Evaluates a string";
static char *eval_descrip =
"Usage: Eval(newvar=somestring)\n"
" Normally Asterisk evaluates variables inline. But what if you want to\n"
"store variable offsets in a database, to be evaluated later? Eval is\n"
"the answer, by allowing a string to be evaluated twice in the dialplan,\n"
"the first time as part of the normal dialplan, and the second using Eval.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int eval_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
char *s, *newvar=NULL, tmp[MAXRESULT];
static int dep_warning = 0;
LOCAL_USER_ADD(u);
if (!dep_warning) {
ast_log(LOG_WARNING, "This application has been deprecated in favor of the dialplan function, EVAL\n");
dep_warning = 1;
}
/* Check and parse arguments */
if (data) {
s = ast_strdupa((char *)data);
if (s) {
newvar = strsep(&s, "=");
if (newvar && (newvar[0] != '\0')) {
memset(tmp, 0, MAXRESULT);
pbx_substitute_variables_helper(chan, s, tmp, MAXRESULT - 1);
pbx_builtin_setvar_helper(chan, newvar, tmp);
}
} else {
ast_log(LOG_ERROR, "Out of memory\n");
res = -1;
}
}
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
int res;
res = ast_unregister_application(app_eval);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
int load_module(void)
{
return ast_register_application(app_eval, eval_exec, eval_synopsis, eval_descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -2,9 +2,8 @@
* Asterisk -- An open source telephony toolkit.
*
* Copyright (c) 2004 - 2005, Tilghman Lesher. All rights reserved.
* Portions copyright (c) 2006, Philipp Dunkel.
*
* Tilghman Lesher <app_exec__v002@the-tilghman.com>
* Tilghman Lesher <app_exec__v001@the-tilghman.com>
*
* This code is released by the author with no restrictions on usage.
*
@@ -20,21 +19,20 @@
*
* \brief Exec application
*
* \author Tilghman Lesher <app_exec__v002@the-tilghman.com>
* \author Philipp Dunkel <philipp.dunkel@ebox.at>
* \author Tilghman Lesher <app_exec__v001@the-tilghman.com>
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
@@ -45,177 +43,93 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
/* Maximum length of any variable */
#define MAXRESULT 1024
/*! Note
*
* The key difference between these two apps is exit status. In a
* nutshell, Exec tries to be transparent as possible, behaving
* in exactly the same way as if the application it calls was
* directly invoked from the dialplan.
*
* TryExec, on the other hand, provides a way to execute applications
* and catch any possible fatal error without actually fatally
* affecting the dialplan.
*/
static char *tdesc = "Executes applications";
static char *app_exec = "Exec";
static char *exec_synopsis = "Executes dialplan application";
static char *exec_synopsis = "Executes internal application";
static char *exec_descrip =
"Usage: Exec(appname(arguments))\n"
" Allows an arbitrary application to be invoked even when not\n"
"hardcoded into the dialplan. If the underlying application\n"
"terminates the dialplan, or if the application cannot be found,\n"
"Exec will terminate the dialplan.\n"
" To invoke external applications, see the application System.\n"
" If you would like to catch any error instead, see TryExec.\n";
static char *app_tryexec = "TryExec";
static char *tryexec_synopsis = "Executes dialplan application, always returning";
static char *tryexec_descrip =
"Usage: TryExec(appname(arguments))\n"
" Allows an arbitrary application to be invoked even when not\n"
"hardcoded into the dialplan. To invoke external applications\n"
"see the application System. Always returns to the dialplan.\n"
"The channel variable TRYSTATUS will be set to:\n"
" SUCCESS if the application returned zero\n"
" FAILED if the application returned non-zero\n"
" NOAPP if the application was not found or was not specified\n";
"see the application System. Returns whatever value the\n"
"app returns or a non-zero value if the app cannot be found.\n";
static char *app_execif = "ExecIf";
static char *execif_synopsis = "Executes dialplan application, conditionally";
static char *execif_descrip =
"Usage: ExecIF (<expr>|<app>|<data>)\n"
"If <expr> is true, execute and return the result of <app>(<data>).\n"
"If <expr> is true, but <app> is not found, then the application\n"
"will return a non-zero value.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int exec_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct ast_module_user *u;
char *s, *appname, *endargs, args[MAXRESULT] = "";
struct localuser *u;
char *s, *appname, *endargs, args[MAXRESULT];
struct ast_app *app;
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
memset(args, 0, MAXRESULT);
/* Check and parse arguments */
if (data) {
s = ast_strdupa(data);
appname = strsep(&s, "(");
s = ast_strdupa((char *)data);
if (s) {
endargs = strrchr(s, ')');
if (endargs)
*endargs = '\0';
pbx_substitute_variables_helper(chan, s, args, MAXRESULT - 1);
}
if (appname) {
app = pbx_findapp(appname);
if (app) {
res = pbx_exec(chan, app, args);
} else {
ast_log(LOG_WARNING, "Could not find application (%s)\n", appname);
res = -1;
appname = strsep(&s, "(");
if (s) {
endargs = strrchr(s, ')');
if (endargs)
*endargs = '\0';
pbx_substitute_variables_helper(chan, s, args, MAXRESULT - 1);
}
if (appname) {
app = pbx_findapp(appname);
if (app) {
res = pbx_exec(chan, app, args, 1);
} else {
ast_log(LOG_WARNING, "Could not find application (%s)\n", appname);
res = -1;
}
}
} else {
ast_log(LOG_ERROR, "Out of memory\n");
res = -1;
}
}
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return res;
}
static int tryexec_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct ast_module_user *u;
char *s, *appname, *endargs, args[MAXRESULT] = "";
struct ast_app *app;
u = ast_module_user_add(chan);
/* Check and parse arguments */
if (data) {
s = ast_strdupa(data);
appname = strsep(&s, "(");
if (s) {
endargs = strrchr(s, ')');
if (endargs)
*endargs = '\0';
pbx_substitute_variables_helper(chan, s, args, MAXRESULT - 1);
}
if (appname) {
app = pbx_findapp(appname);
if (app) {
res = pbx_exec(chan, app, args);
pbx_builtin_setvar_helper(chan, "TRYSTATUS", res ? "FAILED" : "SUCCESS");
} else {
ast_log(LOG_WARNING, "Could not find application (%s)\n", appname);
pbx_builtin_setvar_helper(chan, "TRYSTATUS", "NOAPP");
}
}
}
ast_module_user_remove(u);
return 0;
}
static int execif_exec(struct ast_channel *chan, void *data)
{
int res = 0;
struct ast_module_user *u;
char *myapp = NULL;
char *mydata = NULL;
char *expr = NULL;
struct ast_app *app = NULL;
u = ast_module_user_add(chan);
expr = ast_strdupa(data);
if ((myapp = strchr(expr,'|'))) {
*myapp = '\0';
myapp++;
if ((mydata = strchr(myapp,'|'))) {
*mydata = '\0';
mydata++;
} else
mydata = "";
if (pbx_checkcondition(expr)) {
if ((app = pbx_findapp(myapp))) {
res = pbx_exec(chan, app, mydata);
} else {
ast_log(LOG_WARNING, "Could not find application! (%s)\n", myapp);
res = -1;
}
}
} else {
ast_log(LOG_ERROR,"Invalid Syntax.\n");
res = -1;
}
ast_module_user_remove(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app_exec);
res |= ast_unregister_application(app_tryexec);
res |= ast_unregister_application(app_execif);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
int res = ast_register_application(app_exec, exec_exec, exec_synopsis, exec_descrip);
res |= ast_register_application(app_tryexec, tryexec_exec, tryexec_synopsis, tryexec_descrip);
res |= ast_register_application(app_execif, execif_exec, execif_synopsis, execif_descrip);
return ast_register_application(app_exec, exec_exec, exec_synopsis, exec_descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Executes dialplan applications");
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -22,32 +22,19 @@
/*! \file
*
* \brief External IVR application interface
*
* \author Kevin P. Fleming <kpfleming@digium.com>
*
* \note Portions taken from the file-based music-on-hold work
* created by Anthony Minessale II in res_musiconhold.c
*
*
* \ingroup applications
*/
/*** MODULEINFO
<depend>working_fork</depend>
***/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#ifdef HAVE_CAP
#include <sys/capability.h>
#endif /* HAVE_CAP */
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
@@ -57,22 +44,22 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
#include "asterisk/linkedlists.h"
#include "asterisk/app.h"
#include "asterisk/utils.h"
#include "asterisk/options.h"
static const char *tdesc = "External IVR Interface Application";
static const char *app = "ExternalIVR";
static const char *synopsis = "Interfaces with an external IVR application";
static const char *descrip =
" ExternalIVR(command[|arg[|arg...]]): Forks a process to run the supplied command,\n"
" ExternalIVR(command[|arg[|arg...]]): Forks an process to run the supplied command,\n"
"and starts a generator on the channel. The generator's play list is\n"
"controlled by the external application, which can add and clear entries\n"
"via simple commands issued over its stdout. The external application\n"
"will receive all DTMF events received on the channel, and notification\n"
"if the channel is hung up. The application will not be forcibly terminated\n"
"when the channel is hung up.\n"
"See doc/externalivr.txt for a protocol specification.\n";
"See doc/README.externalivr for a protocol specification.\n";
/* XXX the parser in gcc 2.95 gets confused if you don't put a space between 'name' and the comma */
#define ast_chan_log(level, channel, format, ...) ast_log(level, "%s: " format, channel->name , ## __VA_ARGS__)
@@ -82,8 +69,9 @@ struct playlist_entry {
char filename[1];
};
struct ivr_localuser {
struct localuser {
struct ast_channel *chan;
struct localuser *next;
AST_LIST_HEAD(playlist, playlist_entry) playlist;
AST_LIST_HEAD(finishlist, playlist_entry) finishlist;
int abort_current_sound;
@@ -91,9 +79,10 @@ struct ivr_localuser {
int option_autoclear;
};
LOCAL_USER_DECL;
struct gen_state {
struct ivr_localuser *u;
struct localuser *u;
struct ast_filestream *stream;
struct playlist_entry *current;
int sample_queue;
@@ -116,10 +105,12 @@ static void send_child_event(FILE *handle, const char event, const char *data,
static void *gen_alloc(struct ast_channel *chan, void *params)
{
struct ivr_localuser *u = params;
struct localuser *u = params;
struct gen_state *state;
if (!(state = ast_calloc(1, sizeof(*state))))
state = calloc(1, sizeof(*state));
if (!state)
return NULL;
state->u = u;
@@ -148,7 +139,7 @@ static void gen_release(struct ast_channel *chan, void *data)
/* caller has the playlist locked */
static int gen_nextfile(struct gen_state *state)
{
struct ivr_localuser *u = state->u;
struct localuser *u = state->u;
char *file_to_stream;
u->abort_current_sound = 0;
@@ -160,7 +151,7 @@ static int gen_nextfile(struct gen_state *state)
if (state->current) {
file_to_stream = state->current->filename;
} else {
file_to_stream = "silence/10";
file_to_stream = "silence-10";
u->playing_silence = 1;
}
@@ -180,7 +171,7 @@ static int gen_nextfile(struct gen_state *state)
static struct ast_frame *gen_readframe(struct gen_state *state)
{
struct ast_frame *f = NULL;
struct ivr_localuser *u = state->u;
struct localuser *u = state->u;
if (u->abort_current_sound ||
(u->playing_silence && AST_LIST_FIRST(&u->playlist))) {
@@ -238,8 +229,10 @@ static struct ast_generator gen =
static struct playlist_entry *make_entry(const char *filename)
{
struct playlist_entry *entry;
if (!(entry = ast_calloc(1, sizeof(*entry) + strlen(filename) + 10))) /* XXX why 10 ? */
entry = calloc(1, sizeof(*entry) + strlen(filename) + 10);
if (!entry)
return NULL;
strcpy(entry->filename, filename);
@@ -249,14 +242,13 @@ static struct playlist_entry *make_entry(const char *filename)
static int app_exec(struct ast_channel *chan, void *data)
{
struct ast_module_user *lu;
struct localuser *u = NULL;
struct playlist_entry *entry;
const char *args = data;
int child_stdin[2] = { 0,0 };
int child_stdout[2] = { 0,0 };
int child_stderr[2] = { 0,0 };
int res = -1;
int test_available_fd = -1;
int gen_active = 0;
int pid;
char *argv[32];
@@ -265,28 +257,24 @@ static int app_exec(struct ast_channel *chan, void *data)
FILE *child_commands = NULL;
FILE *child_errors = NULL;
FILE *child_events = NULL;
struct ivr_localuser foo = {
.playlist = AST_LIST_HEAD_INIT_VALUE,
.finishlist = AST_LIST_HEAD_INIT_VALUE,
};
struct ivr_localuser *u = &foo;
sigset_t fullset, oldset;
lu = ast_module_user_add(chan);
sigfillset(&fullset);
pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
LOCAL_USER_ADD(u);
AST_LIST_HEAD_INIT(&u->playlist);
AST_LIST_HEAD_INIT(&u->finishlist);
u->abort_current_sound = 0;
u->chan = chan;
if (ast_strlen_zero(args)) {
ast_log(LOG_WARNING, "ExternalIVR requires a command to execute\n");
ast_module_user_remove(lu);
return -1;
goto exit;
}
buf = ast_strdupa(data);
if (!buf) {
ast_log(LOG_ERROR, "Out of memory!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
argc = ast_app_separate_args(buf, '|', argv, sizeof(argv) / sizeof(argv[0]));
@@ -324,21 +312,6 @@ static int app_exec(struct ast_channel *chan, void *data)
if (!pid) {
/* child process */
int i;
#ifdef HAVE_CAP
cap_t cap = cap_from_text("cap_net_admin-eip");
if (cap_set_proc(cap)) {
/* Careful with order! Logging cannot happen after we close FDs */
ast_log(LOG_WARNING, "Unable to remove capabilities.\n");
}
cap_free(cap);
#endif
signal(SIGPIPE, SIG_DFL);
pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
if (ast_opt_high_priority)
ast_set_priority(0);
dup2(child_stdin[0], STDIN_FILENO);
dup2(child_stdout[1], STDOUT_FILENO);
@@ -347,7 +320,7 @@ static int app_exec(struct ast_channel *chan, void *data)
close(i);
execv(argv[0], argv);
fprintf(stderr, "Failed to execute '%s': %s\n", argv[0], strerror(errno));
_exit(1);
exit(1);
} else {
/* parent process */
int child_events_fd = child_stdin[1];
@@ -360,8 +333,6 @@ static int app_exec(struct ast_channel *chan, void *data)
int waitfds[2] = { child_errors_fd, child_commands_fd };
struct ast_channel *rchan;
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
close(child_stdin[0]);
child_stdin[0] = 0;
close(child_stdout[1]);
@@ -384,8 +355,6 @@ static int app_exec(struct ast_channel *chan, void *data)
goto exit;
}
test_available_fd = open("/dev/null", O_RDONLY);
setvbuf(child_events, NULL, _IONBF, 0);
setvbuf(child_commands, NULL, _IONBF, 0);
setvbuf(child_errors, NULL, _IONBF, 0);
@@ -474,7 +443,7 @@ static int app_exec(struct ast_channel *chan, void *data)
continue;
if (input[0] == 'S') {
if (ast_fileexists(&input[2], NULL, u->chan->language) == -1) {
if (ast_fileexists(&input[2], NULL, NULL) == -1) {
ast_chan_log(LOG_WARNING, chan, "Unknown file requested '%s'\n", &input[2]);
send_child_event(child_events, 'Z', NULL, chan);
strcpy(&input[2], "exception");
@@ -493,7 +462,7 @@ static int app_exec(struct ast_channel *chan, void *data)
AST_LIST_INSERT_TAIL(&u->playlist, entry, list);
AST_LIST_UNLOCK(&u->playlist);
} else if (input[0] == 'A') {
if (ast_fileexists(&input[2], NULL, u->chan->language) == -1) {
if (ast_fileexists(&input[2], NULL, NULL) == -1) {
ast_chan_log(LOG_WARNING, chan, "Unknown file requested '%s'\n", &input[2]);
send_child_event(child_events, 'Z', NULL, chan);
strcpy(&input[2], "exception");
@@ -519,7 +488,7 @@ static int app_exec(struct ast_channel *chan, void *data)
} else if (ready_fd == child_errors_fd) {
char input[1024];
if (exception || (dup2(child_commands_fd, test_available_fd) == -1) || feof(child_errors)) {
if (exception || feof(child_errors)) {
ast_chan_log(LOG_WARNING, chan, "Child process went away\n");
res = -1;
break;
@@ -552,10 +521,6 @@ static int app_exec(struct ast_channel *chan, void *data)
if (child_errors)
fclose(child_errors);
if (test_available_fd > -1) {
close(test_available_fd);
}
if (child_stdin[0])
close(child_stdin[0]);
@@ -577,25 +542,42 @@ static int app_exec(struct ast_channel *chan, void *data)
while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list)))
free(entry);
ast_module_user_remove(lu);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, app_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "External IVR Interface Application");
char *description(void)
{
return (char *) tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,20 +19,10 @@
/*! \file
*
* \brief Connect to festival
*
* \author Christos Ricudis <ricudis@itc.auth.gr>
*
* \ingroup applications
*/
/*** MODULEINFO
<depend>working_fork</depend>
***/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
@@ -49,10 +39,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
#include <errno.h>
#ifdef HAVE_CAP
#include <sys/capability.h>
#endif /* HAVE_CAP */
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
@@ -63,10 +53,11 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/config.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/options.h"
#define FESTIVAL_CONFIG "festival.conf"
static char *tdesc = "Simple Festival Interface";
static char *app = "Festival";
static char *synopsis = "Say text to the user";
@@ -76,6 +67,9 @@ static char *descrip =
"play it to the user, allowing any given interrupt keys to immediately terminate and return\n"
"the value, or 'any' to allow any number back (useful in dialplan)\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static char *socket_receive_file_to_buff(int fd,int *size)
{
@@ -90,10 +84,7 @@ static char *socket_receive_file_to_buff(int fd,int *size)
char c;
bufflen = 1024;
if (!(buff = ast_malloc(bufflen)))
{
/* TODO: Handle memory allocation failure */
}
buff = (char *)malloc(bufflen);
*size=0;
for (k=0; file_stuff_key[k] != '\0';)
@@ -103,10 +94,7 @@ static char *socket_receive_file_to_buff(int fd,int *size)
if ((*size)+k+1 >= bufflen)
{ /* +1 so you can add a NULL if you want */
bufflen += bufflen/4;
if (!(buff = ast_realloc(buff, bufflen)))
{
/* TODO: Handle memory allocation failure */
}
buff = (char *)realloc(buff,bufflen);
}
if (file_stuff_key[k] == c)
k++;
@@ -138,38 +126,16 @@ static int send_waveform_to_fd(char *waveform, int length, int fd) {
#ifdef __PPC__
char c;
#endif
sigset_t fullset, oldset;
#ifdef HAVE_CAP
cap_t cap;
#endif
sigfillset(&fullset);
pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
res = fork();
if (res < 0)
ast_log(LOG_WARNING, "Fork failed\n");
if (res) {
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
return res;
}
#ifdef HAVE_CAP
cap = cap_from_text("cap_net_admin-eip");
if (cap_set_proc(cap)) {
/* Careful with order! Logging cannot happen after we close FDs */
ast_log(LOG_WARNING, "Unable to remove capabilities.\n");
}
cap_free(cap);
#endif
for (x=0;x<256;x++) {
if (x != fd)
close(x);
}
if (ast_opt_high_priority)
ast_set_priority(0);
signal(SIGPIPE, SIG_DFL);
pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
res = fork();
if (res < 0)
ast_log(LOG_WARNING, "Fork failed\n");
if (res)
return res;
for (x=0;x<256;x++) {
if (x != fd)
close(x);
}
/*IAS */
#ifdef __PPC__
for( x=0; x<length; x+=2)
@@ -180,9 +146,7 @@ static int send_waveform_to_fd(char *waveform, int length, int fd) {
}
#endif
if (write(fd,waveform,length) < 0) {
ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
}
write(fd,waveform,length);
close(fd);
exit(0);
}
@@ -200,9 +164,7 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
struct ast_frame f;
char offset[AST_FRIENDLY_OFFSET];
char frdata[2048];
} myf = {
.f = { 0, },
};
} myf;
if (pipe(fds)) {
ast_log(LOG_WARNING, "Unable to create pipe\n");
@@ -262,18 +224,17 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
myf.f.subclass = AST_FORMAT_SLINEAR;
myf.f.datalen = res;
myf.f.samples = res / 2;
myf.f.mallocd = 0;
myf.f.offset = AST_FRIENDLY_OFFSET;
myf.f.src = __PRETTY_FUNCTION__;
myf.f.data = myf.frdata;
if (ast_write(chan, &myf.f) < 0) {
res = -1;
ast_frfree(f);
break;
}
if (res < needed) { /* last frame */
ast_log(LOG_DEBUG, "Last frame\n");
res=0;
ast_frfree(f);
break;
}
} else {
@@ -304,16 +265,16 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
{
int usecache;
int res=0;
struct ast_module_user *u;
struct localuser *u;
struct sockaddr_in serv_addr;
struct hostent *serverhost;
struct ast_hostent ahp;
int fd;
FILE *fs;
const char *host;
const char *cachedir;
const char *temp;
const char *festivalcommand;
char *host;
char *cachedir;
char *temp;
char *festivalcommand;
int port=1314;
int n;
char ack[4];
@@ -336,19 +297,18 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
char *data;
char *intstr;
struct ast_config *cfg;
char *newfestivalcommand;
if (ast_strlen_zero(vdata)) {
ast_log(LOG_WARNING, "festival requires an argument (text)\n");
return -1;
}
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
cfg = ast_config_load(FESTIVAL_CONFIG);
if (!cfg) {
ast_log(LOG_WARNING, "No such configuration file %s\n", FESTIVAL_CONFIG);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
if (!(host = ast_variable_retrieve(cfg, "general", "host"))) {
@@ -369,25 +329,15 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
}
if (!(festivalcommand = ast_variable_retrieve(cfg, "general", "festivalcommand"))) {
festivalcommand = "(tts_textasterisk \"%s\" 'file)(quit)\n";
} else { /* This else parses the festivalcommand that we're sent from the config file for \n's, etc */
int i, j;
newfestivalcommand = alloca(strlen(festivalcommand) + 1);
for (i = 0, j = 0; i < strlen(festivalcommand); i++) {
if (festivalcommand[i] == '\\' && festivalcommand[i + 1] == 'n') {
newfestivalcommand[j++] = '\n';
i++;
} else if (festivalcommand[i] == '\\') {
newfestivalcommand[j++] = festivalcommand[i + 1];
i++;
} else
newfestivalcommand[j++] = festivalcommand[i];
}
newfestivalcommand[j] = '\0';
festivalcommand = newfestivalcommand;
}
data = ast_strdupa(vdata);
if (!data) {
ast_log(LOG_ERROR, "Out of memery\n");
ast_config_destroy(cfg);
LOCAL_USER_REMOVE(u);
return -1;
}
intstr = strchr(data, '|');
if (intstr) {
@@ -405,7 +355,7 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
if (fd < 0) {
ast_log(LOG_WARNING,"festival_client: can't get socket\n");
ast_config_destroy(cfg);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
memset(&serv_addr, 0, sizeof(serv_addr));
@@ -415,7 +365,7 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
if (serverhost == (struct hostent *)0) {
ast_log(LOG_WARNING,"festival_client: gethostbyname failed\n");
ast_config_destroy(cfg);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
memmove(&serv_addr.sin_addr,serverhost->h_addr, serverhost->h_length);
@@ -426,7 +376,7 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
if (connect(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != 0) {
ast_log(LOG_WARNING,"festival_client: connect to server failed\n");
ast_config_destroy(cfg);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
@@ -453,25 +403,17 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
writecache=1;
strln=strlen((char *)data);
ast_log(LOG_DEBUG,"line length : %d\n",strln);
if (write(fdesc,&strln,sizeof(int)) < 0) {
ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
}
if (write(fdesc,data,strln) < 0) {
ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
}
write(fdesc,&strln,sizeof(int));
write(fdesc,data,strln);
seekpos=lseek(fdesc,0,SEEK_CUR);
ast_log(LOG_DEBUG,"Seek position : %d\n",seekpos);
}
} else {
if (read(fdesc,&strln,sizeof(int)) != sizeof(int)) {
ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
}
read(fdesc,&strln,sizeof(int));
ast_log(LOG_DEBUG,"Cache file exists, strln=%d, strlen=%d\n",strln,(int)strlen((char *)data));
if (strlen((char *)data)==strln) {
ast_log(LOG_DEBUG,"Size OK\n");
if (read(fdesc,&bigstring,strln) != strln) {
ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
}
read(fdesc,&bigstring,strln);
bigstring[strln] = 0;
if (strcmp(bigstring,data)==0) {
readcache=1;
@@ -500,9 +442,7 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
if (writecache==1) {
ast_log(LOG_DEBUG,"Writing result to cache...\n");
while ((strln=read(fd,buffer,16384))!=0) {
if (write(fdesc,buffer,strln) < 0) {
ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
}
write(fdesc,buffer,strln);
}
close(fd);
close(fdesc);
@@ -525,10 +465,7 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
* */
if ( read_data == -1 )
{
ast_log(LOG_WARNING,"Unable to read from cache/festival fd\n");
close(fd);
ast_config_destroy(cfg);
ast_module_user_remove(u);
ast_log(LOG_WARNING,"Unable to read from cache/festival fd");
return -1;
}
n += read_data;
@@ -555,31 +492,41 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
} while (strcmp(ack,"OK\n") != 0);
close(fd);
ast_config_destroy(cfg);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
struct ast_config *cfg = ast_config_load(FESTIVAL_CONFIG);
if (!cfg) {
ast_log(LOG_WARNING, "No such configuration file %s\n", FESTIVAL_CONFIG);
return AST_MODULE_LOAD_DECLINE;
}
ast_config_destroy(cfg);
return ast_register_application(app, festival_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Simple Festival Interface");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -18,26 +18,25 @@
/*! \file
*
* \brief App to flash a DAHDI trunk
*
* \author Mark Spencer <markster@digium.com>
* \brief App to flash a zap trunk
*
* \ingroup applications
*/
/*** MODULEINFO
<depend>dahdi</depend>
***/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#ifdef __linux__
#include <linux/zaptel.h>
#else
#include <zaptel.h>
#endif /* __linux__ */
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
@@ -49,33 +48,28 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/image.h"
#include "asterisk/options.h"
#include "asterisk/dahdi_compat.h"
static char *tdesc = "Flash zap trunk application";
static char *app = "Flash";
static char *dahdi_synopsis = "Flashes a DAHDI trunk";
static char *synopsis = "Flashes a Zap Trunk";
static char *dahdi_descrip =
"Performs a flash on a DAHDI trunk. This can be used\n"
"to access features provided on an incoming analogue circuit\n"
"such as conference and call waiting. Use with SendDTMF() to\n"
"perform external transfers\n";
static char *descrip =
" Flash(): Sends a flash on a zap trunk. This is only a hack for\n"
"people who want to perform transfers and such via AGI and is generally\n"
"quite useless oths application will only work on Zap trunks.\n";
static char *zap_synopsis = "Flashes a Zap trunk";
STANDARD_LOCAL_USER;
static char *zap_descrip =
"Performs a flash on a Zap trunk. This can be used\n"
"to access features provided on an incoming analogue circuit\n"
"such as conference and call waiting. Use with SendDTMF() to\n"
"perform external transfers\n";
LOCAL_USER_DECL;
static inline int zt_wait_event(int fd)
{
/* Avoid the silly zt_waitevent which ignores a bunch of events */
int i,j=0;
i = DAHDI_IOMUX_SIGEVENT;
if (ioctl(fd, DAHDI_IOMUX, &i) == -1) return -1;
if (ioctl(fd, DAHDI_GETEVENT, &j) == -1) return -1;
i = ZT_IOMUX_SIGEVENT;
if (ioctl(fd, ZT_IOMUX, &i) == -1) return -1;
if (ioctl(fd, ZT_GETEVENT, &j) == -1) return -1;
return j;
}
@@ -83,16 +77,16 @@ static int flash_exec(struct ast_channel *chan, void *data)
{
int res = -1;
int x;
struct ast_module_user *u;
struct dahdi_params ztp;
u = ast_module_user_add(chan);
if (!strcasecmp(chan->tech->type, dahdi_chan_name)) {
struct localuser *u;
struct zt_params ztp;
LOCAL_USER_ADD(u);
if (!strcasecmp(chan->type, "Zap")) {
memset(&ztp, 0, sizeof(ztp));
res = ioctl(chan->fds[0], DAHDI_GET_PARAMS, &ztp);
res = ioctl(chan->fds[0], ZT_GET_PARAMS, &ztp);
if (!res) {
if (ztp.sigtype & __DAHDI_SIG_FXS) {
x = DAHDI_FLASH;
res = ioctl(chan->fds[0], DAHDI_HOOK, &x);
if (ztp.sigtype & __ZT_SIG_FXS) {
x = ZT_FLASH;
res = ioctl(chan->fds[0], ZT_HOOK, &x);
if (!res || (errno == EINPROGRESS)) {
if (res) {
/* Wait for the event to finish */
@@ -108,29 +102,40 @@ static int flash_exec(struct ast_channel *chan, void *data)
} else
ast_log(LOG_WARNING, "Unable to get parameters of %s: %s\n", chan->name, strerror(errno));
} else
ast_log(LOG_WARNING, "%s is not a DAHDI channel\n", chan->name);
ast_module_user_remove(u);
ast_log(LOG_WARNING, "%s is not a Zap channel\n", chan->name);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
if (dahdi_chan_mode == CHAN_ZAP_MODE) {
return ast_register_application(app, flash_exec, zap_synopsis, zap_descrip);
} else {
return ast_register_application(app, flash_exec, dahdi_synopsis, dahdi_descrip);
}
return ast_register_application(app, flash_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Flash channel application");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

File diff suppressed because it is too large Load Diff

View File

@@ -18,148 +18,42 @@
/*! \file
*
* \brief Fork CDR application
*
* \author Anthony Minessale anthmct@yahoo.com
*
* \note Development of this app Sponsored/Funded by TAAN Softworks Corp
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/cdr.h"
#include "asterisk/app.h"
#include "asterisk/module.h"
static char *tdesc = "Fork The CDR into 2 separate entities.";
static char *app = "ForkCDR";
static char *synopsis =
"Forks the Call Data Record";
static char *descrip =
" ForkCDR([options]): Causes the Call Data Record to fork an additional\n"
"cdr record starting from the time of the fork call. This new cdr record will\n"
"be linked to end of the list of cdr records attached to the channel. The original CDR is\n"
"has a LOCKED flag set, which forces most cdr operations to skip it, except\n"
"for the functions that set the answer and end times, which ignore the LOCKED\n"
"flag. This allows all the cdr records in the channel to be 'ended' together\n"
"when the channel is closed.\n"
"The CDR() func (when setting CDR values) normally ignores the LOCKED flag also,\n"
"but has options to vary its behavior. The 'T' option (described below), can\n"
"override this behavior, but beware the risks.\n"
"\n"
"Detailed Behavior Description:\n"
"First, this app finds the last cdr record in the list, and makes\n"
"a copy of it. This new copy will be the newly forked cdr record.\n"
"Next, this new record is linked to the end of the cdr record list.\n"
"Next, The new cdr record is RESET (unless you use an option to prevent this)\n"
"This means that:\n"
" 1. All flags are unset on the cdr record\n"
" 2. the start, end, and answer times are all set to zero.\n"
" 3. the billsec and duration fields are set to zero.\n"
" 4. the start time is set to the current time.\n"
" 5. the disposition is set to NULL.\n"
"Next, unless you specified the 'v' option, all variables will be\n"
"removed from the original cdr record. Thus, the 'v' option allows\n"
"any CDR variables to be replicated to all new forked cdr records.\n"
"Without the 'v' option, the variables on the original are effectively\n"
"moved to the new forked cdr record.\n"
"Next, if the 's' option is set, the provided variable and value\n"
"are set on the original cdr record.\n"
"Next, if the 'a' option is given, and the original cdr record has an\n"
"answer time set, then the new forked cdr record will have its answer\n"
"time set to its start time. If the old answer time were carried forward,\n"
"the answer time would be earlier than the start time, giving strange\n"
"duration and billsec times.\n"
"Next, if the 'd' option was specified, the disposition is copied from\n"
"the original cdr record to the new forked cdr.\n"
"Next, if the 'D' option was specified, the destination channel field\n"
"in the new forked CDR is erased.\n"
"Next, if the 'e' option was specified, the 'end' time for the original\n"
"cdr record is set to the current time. Future hang-up or ending events\n"
"will not override this time stamp.\n"
"Next, If the 'A' option is specified, the original cdr record will have\n"
"it ANS_LOCKED flag set, which prevent future answer events\n"
"from updating the original cdr record's disposition. Normally, an\n"
"'ANSWERED' event would mark all cdr records in the chain as 'ANSWERED'.\n"
"Next, if the 'T' option is specified, the original cdr record will have\n"
"its 'DONT_TOUCH' flag set, which will force the cdr_answer, cdr_end, and\n"
"cdr_setvar functions to leave that cdr record alone.\n"
"And, last but not least, the original cdr record has its LOCKED flag\n"
"set. Almost all internal CDR functions (except for the funcs that set\n"
"the end, and answer times, and set a variable) will honor this flag\n"
"and leave a LOCKED cdr record alone.\n"
"This means that the newly created forked cdr record will affected\n"
"by events transpiring within Asterisk, with the previously noted\n"
"exceptions.\n"
" Options:\n"
" a - update the answer time on the NEW CDR just after it's been inited..\n"
" The new CDR may have been answered already, the reset that forkcdr.\n"
" does will erase the answer time. This will bring it back, but\n"
" the answer time will be a copy of the fork/start time. It will.\n"
" only do this if the initial cdr was indeed already answered..\n"
" A - Lock the original CDR against the answer time being updated.\n"
" This will allow the disposition on the original CDR to remain the same.\n"
" d - Copy the disposition forward from the old cdr, after the .\n"
" init..\n"
" D - Clear the dstchannel on the new CDR after reset..\n"
" e - end the original CDR. Do this after all the necc. data.\n"
" is copied from the original CDR to the new forked CDR..\n"
" R - do NOT reset the new cdr..\n"
" s(name=val) - Set the CDR var 'name' in the original CDR, with value.\n"
" 'val'.\n"
" T - Mark the original CDR with a DONT_TOUCH flag. setvar, answer, and end\n"
" cdr funcs will obey this flag; normally they don't honor the LOCKED\n"
" flag set on the original CDR record.\n"
" Beware-- using this flag may cause CDR's not to have their end times\n"
" updated! It is suggested that if you specify this flag, you might\n"
" wish to use the 'e' flag as well!\n"
" v - When the new CDR is forked, it gets a copy of the vars attached\n"
" to the current CDR. The vars attached to the original CDR are removed\n"
" unless this option is specified.\n";
"cdr record starting from the time of the fork call\n"
"If the option 'v' is passed all cdr variables will be passed along also.\n"
"";
enum {
OPT_SETANS = (1 << 0),
OPT_SETDISP = (1 << 1),
OPT_RESETDEST = (1 << 2),
OPT_ENDCDR = (1 << 3),
OPT_NORESET = (1 << 4),
OPT_KEEPVARS = (1 << 5),
OPT_VARSET = (1 << 6),
OPT_ANSLOCK = (1 << 7),
OPT_DONTOUCH = (1 << 8),
};
STANDARD_LOCAL_USER;
enum {
OPT_ARG_VARSET = 0,
/* note: this entry _MUST_ be the last one in the enum */
OPT_ARG_ARRAY_SIZE,
};
LOCAL_USER_DECL;
AST_APP_OPTIONS(forkcdr_exec_options, {
AST_APP_OPTION('a', OPT_SETANS),
AST_APP_OPTION('A', OPT_ANSLOCK),
AST_APP_OPTION('d', OPT_SETDISP),
AST_APP_OPTION('D', OPT_RESETDEST),
AST_APP_OPTION('e', OPT_ENDCDR),
AST_APP_OPTION('R', OPT_NORESET),
AST_APP_OPTION_ARG('s', OPT_VARSET, OPT_ARG_VARSET),
AST_APP_OPTION('T', OPT_DONTOUCH),
AST_APP_OPTION('v', OPT_KEEPVARS),
});
static void ast_cdr_fork(struct ast_channel *chan, struct ast_flags optflags, char *set)
static void ast_cdr_fork(struct ast_channel *chan)
{
struct ast_cdr *cdr;
struct ast_cdr *newcdr;
@@ -174,94 +68,64 @@ static void ast_cdr_fork(struct ast_channel *chan, struct ast_flags optflags, ch
return;
ast_cdr_append(cdr, newcdr);
if (!ast_test_flag(&optflags, OPT_NORESET))
ast_cdr_reset(newcdr, &flags);
ast_cdr_reset(newcdr, &flags);
if (!ast_test_flag(cdr, AST_CDR_FLAG_KEEP_VARS))
ast_cdr_free_vars(cdr, 0);
if (!ast_strlen_zero(set)) {
char *varname = ast_strdupa(set), *varval;
varval = strchr(varname,'=');
if (varval) {
*varval = 0;
varval++;
ast_cdr_setvar(cdr, varname, varval, 0);
}
}
if (ast_test_flag(&optflags, OPT_SETANS) && !ast_tvzero(cdr->answer))
newcdr->answer = newcdr->start;
if (ast_test_flag(&optflags, OPT_SETDISP))
newcdr->disposition = cdr->disposition;
if (ast_test_flag(&optflags, OPT_RESETDEST))
newcdr->dstchannel[0] = 0;
if (ast_test_flag(&optflags, OPT_ENDCDR))
ast_cdr_end(cdr);
if (ast_test_flag(&optflags, OPT_ANSLOCK))
ast_set_flag(cdr, AST_CDR_FLAG_ANSLOCKED);
if (ast_test_flag(&optflags, OPT_DONTOUCH))
ast_set_flag(cdr, AST_CDR_FLAG_DONT_TOUCH);
ast_set_flag(cdr, AST_CDR_FLAG_CHILD | AST_CDR_FLAG_LOCKED);
}
static int forkcdr_exec(struct ast_channel *chan, void *data)
{
int res = 0;
struct ast_module_user *u;
char *argcopy = NULL;
struct ast_flags flags = {0};
char *opts[OPT_ARG_ARRAY_SIZE];
AST_DECLARE_APP_ARGS(arglist,
AST_APP_ARG(options);
);
struct localuser *u;
if (!chan->cdr) {
ast_log(LOG_WARNING, "Channel does not have a CDR\n");
return 0;
}
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
argcopy = ast_strdupa(data);
AST_STANDARD_APP_ARGS(arglist, argcopy);
opts[OPT_ARG_VARSET] = 0;
if (!ast_strlen_zero(arglist.options))
ast_app_parse_options(forkcdr_exec_options, &flags, opts, arglist.options);
if (!ast_strlen_zero(data))
ast_set2_flag(chan->cdr, ast_test_flag(&flags, OPT_KEEPVARS), AST_CDR_FLAG_KEEP_VARS);
ast_set2_flag(chan->cdr, strchr(data, 'v'), AST_CDR_FLAG_KEEP_VARS);
ast_cdr_fork(chan, flags, opts[OPT_ARG_VARSET]);
ast_cdr_fork(chan);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, forkcdr_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Fork The CDR into 2 separate entities");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,21 +19,19 @@
/*! \file
*
* \brief Get ADSI CPE ID
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
@@ -43,14 +41,19 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/adsi.h"
#include "asterisk/options.h"
static char *tdesc = "Get ADSI CPE ID";
static char *app = "GetCPEID";
static char *synopsis = "Get ADSI CPE ID";
static char *descrip =
" GetCPEID: Obtains and displays ADSI CPE ID and other information in order\n"
"to properly setup chan_dahdi.conf for on-hook operations.\n";
"to properly setup zapata.conf for on-hook operations.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int cpeid_setstatus(struct ast_channel *chan, char *stuff[], int voice)
{
@@ -60,42 +63,43 @@ static int cpeid_setstatus(struct ast_channel *chan, char *stuff[], int voice)
for (x=0;x<4;x++)
tmp[x] = stuff[x];
tmp[4] = NULL;
return ast_adsi_print(chan, tmp, justify, voice);
return adsi_print(chan, tmp, justify, voice);
}
static int cpeid_exec(struct ast_channel *chan, void *idata)
{
int res=0;
struct ast_module_user *u;
struct localuser *u;
unsigned char cpeid[4];
int gotgeometry = 0;
int gotcpeid = 0;
int width, height, buttons;
char *data[4];
unsigned int x;
char data[4][80];
char *stuff[4];
u = ast_module_user_add(chan);
for (x = 0; x < 4; x++)
data[x] = alloca(80);
strcpy(data[0], "** CPE Info **");
strcpy(data[1], "Identifying CPE...");
strcpy(data[2], "Please wait...");
res = ast_adsi_load_session(chan, NULL, 0, 1);
LOCAL_USER_ADD(u);
stuff[0] = data[0];
stuff[1] = data[1];
stuff[2] = data[2];
stuff[3] = data[3];
memset(data, 0, sizeof(data));
strncpy(stuff[0], "** CPE Info **", sizeof(data[0]) - 1);
strncpy(stuff[1], "Identifying CPE...", sizeof(data[1]) - 1);
strncpy(stuff[2], "Please wait...", sizeof(data[2]) - 1);
res = adsi_load_session(chan, NULL, 0, 1);
if (res > 0) {
cpeid_setstatus(chan, data, 0);
res = ast_adsi_get_cpeid(chan, cpeid, 0);
cpeid_setstatus(chan, stuff, 0);
res = adsi_get_cpeid(chan, cpeid, 0);
if (res > 0) {
gotcpeid = 1;
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Got CPEID of '%02x:%02x:%02x:%02x' on '%s'\n", cpeid[0], cpeid[1], cpeid[2], cpeid[3], chan->name);
}
if (res > -1) {
strcpy(data[1], "Measuring CPE...");
strcpy(data[2], "Please wait...");
cpeid_setstatus(chan, data, 0);
res = ast_adsi_get_cpeinfo(chan, &width, &height, &buttons, 0);
strncpy(stuff[1], "Measuring CPE...", sizeof(data[1]) - 1);
strncpy(stuff[2], "Please wait...", sizeof(data[2]) - 1);
cpeid_setstatus(chan, stuff, 0);
res = adsi_get_cpeinfo(chan, &width, &height, &buttons, 0);
if (res > -1) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "CPE has %d lines, %d columns, and %d buttons on '%s'\n", height, width, buttons, chan->name);
@@ -104,15 +108,15 @@ static int cpeid_exec(struct ast_channel *chan, void *idata)
}
if (res > -1) {
if (gotcpeid)
snprintf(data[1], 80, "CPEID: %02x:%02x:%02x:%02x", cpeid[0], cpeid[1], cpeid[2], cpeid[3]);
snprintf(stuff[1], sizeof(data[1]), "CPEID: %02x:%02x:%02x:%02x", cpeid[0], cpeid[1], cpeid[2], cpeid[3]);
else
strcpy(data[1], "CPEID Unknown");
strncpy(stuff[1], "CPEID Unknown", sizeof(data[1]) - 1);
if (gotgeometry)
snprintf(data[2], 80, "Geom: %dx%d, %d buttons", width, height, buttons);
snprintf(stuff[2], sizeof(data[2]), "Geom: %dx%d, %d buttons", width, height, buttons);
else
strcpy(data[2], "Geometry unknown");
strcpy(data[3], "Press # to exit");
cpeid_setstatus(chan, data, 1);
strncpy(stuff[2], "Geometry unknown", sizeof(data[2]) - 1);
strncpy(stuff[3], "Press # to exit", sizeof(data[3]) - 1);
cpeid_setstatus(chan, stuff, 1);
for(;;) {
res = ast_waitfordigit(chan, 1000);
if (res < 0)
@@ -122,27 +126,42 @@ static int cpeid_exec(struct ast_channel *chan, void *idata)
break;
}
}
ast_adsi_unload_session(chan);
adsi_unload_session(chan);
}
}
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, cpeid_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Get ADSI CPE ID");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

340
apps/app_groupcount.c Normal file
View File

@@ -0,0 +1,340 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2005, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief Group Manipulation Applications
*
* \ingroup applications
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <regex.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int group_count_exec(struct ast_channel *chan, void *data)
{
int res = 0;
int count;
struct localuser *u;
char group[80] = "";
char category[80] = "";
char ret[80] = "";
char *grp;
static int deprecation_warning = 0;
LOCAL_USER_ADD(u);
if (!deprecation_warning) {
ast_log(LOG_WARNING, "The GetGroupCount application has been deprecated, please use the GROUP_COUNT function.\n");
deprecation_warning = 1;
}
ast_app_group_split_group(data, group, sizeof(group), category, sizeof(category));
if (ast_strlen_zero(group)) {
grp = pbx_builtin_getvar_helper(chan, category);
strncpy(group, grp, sizeof(group) - 1);
}
count = ast_app_group_get_count(group, category);
snprintf(ret, sizeof(ret), "%d", count);
pbx_builtin_setvar_helper(chan, "GROUPCOUNT", ret);
LOCAL_USER_REMOVE(u);
return res;
}
static int group_match_count_exec(struct ast_channel *chan, void *data)
{
int res = 0;
int count;
struct localuser *u;
char group[80] = "";
char category[80] = "";
char ret[80] = "";
static int deprecation_warning = 0;
LOCAL_USER_ADD(u);
if (!deprecation_warning) {
ast_log(LOG_WARNING, "The GetGroupMatchCount application has been deprecated, please use the GROUP_MATCH_COUNT function.\n");
deprecation_warning = 1;
}
ast_app_group_split_group(data, group, sizeof(group), category, sizeof(category));
if (!ast_strlen_zero(group)) {
count = ast_app_group_match_get_count(group, category);
snprintf(ret, sizeof(ret), "%d", count);
pbx_builtin_setvar_helper(chan, "GROUPCOUNT", ret);
}
LOCAL_USER_REMOVE(u);
return res;
}
static int group_set_exec(struct ast_channel *chan, void *data)
{
int res = 0;
struct localuser *u;
static int deprecation_warning = 0;
LOCAL_USER_ADD(u);
if (!deprecation_warning) {
ast_log(LOG_WARNING, "The SetGroup application has been deprecated, please use the GROUP() function.\n");
deprecation_warning = 1;
}
if (ast_app_group_set_channel(chan, data))
ast_log(LOG_WARNING, "SetGroup requires an argument (group name)\n");
LOCAL_USER_REMOVE(u);
return res;
}
static int group_check_exec(struct ast_channel *chan, void *data)
{
int res = 0;
int max, count;
struct localuser *u;
char limit[80]="";
char category[80]="";
static int deprecation_warning = 0;
char *parse;
int priority_jump = 0;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(max);
AST_APP_ARG(options);
);
LOCAL_USER_ADD(u);
if (!deprecation_warning) {
ast_log(LOG_WARNING, "The CheckGroup application has been deprecated, please use a combination of the GotoIf application and the GROUP_COUNT() function.\n");
deprecation_warning = 1;
}
if (!(parse = ast_strdupa(data))) {
ast_log(LOG_WARNING, "Memory Error!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
AST_STANDARD_APP_ARGS(args, parse);
if (args.options) {
if (strchr(args.options, 'j'))
priority_jump = 1;
}
if (ast_strlen_zero(args.max)) {
ast_log(LOG_WARNING, "CheckGroup requires an argument(max[@category][|options])\n");
return res;
}
ast_app_group_split_group(args.max, limit, sizeof(limit), category, sizeof(category));
if ((sscanf(limit, "%d", &max) == 1) && (max > -1)) {
count = ast_app_group_get_count(pbx_builtin_getvar_helper(chan, category), category);
if (count > max) {
pbx_builtin_setvar_helper(chan, "CHECKGROUPSTATUS", "OVERMAX");
if (priority_jump || option_priority_jumping) {
if (!ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101))
res = -1;
}
} else
pbx_builtin_setvar_helper(chan, "CHECKGROUPSTATUS", "OK");
} else
ast_log(LOG_WARNING, "CheckGroup requires a positive integer argument (max)\n");
LOCAL_USER_REMOVE(u);
return res;
}
static int group_show_channels(int fd, int argc, char *argv[])
{
#define FORMAT_STRING "%-25s %-20s %-20s\n"
struct ast_channel *c = NULL;
int numchans = 0;
struct ast_var_t *current;
struct varshead *headp;
regex_t regexbuf;
int havepattern = 0;
if (argc < 3 || argc > 4)
return RESULT_SHOWUSAGE;
if (argc == 4) {
if (regcomp(&regexbuf, argv[3], REG_EXTENDED | REG_NOSUB))
return RESULT_SHOWUSAGE;
havepattern = 1;
}
ast_cli(fd, FORMAT_STRING, "Channel", "Group", "Category");
while ( (c = ast_channel_walk_locked(c)) != NULL) {
headp=&c->varshead;
AST_LIST_TRAVERSE(headp,current,entries) {
if (!strncmp(ast_var_name(current), GROUP_CATEGORY_PREFIX "_", strlen(GROUP_CATEGORY_PREFIX) + 1)) {
if (!havepattern || !regexec(&regexbuf, ast_var_value(current), 0, NULL, 0)) {
ast_cli(fd, FORMAT_STRING, c->name, ast_var_value(current),
(ast_var_name(current) + strlen(GROUP_CATEGORY_PREFIX) + 1));
numchans++;
}
} else if (!strcmp(ast_var_name(current), GROUP_CATEGORY_PREFIX)) {
if (!havepattern || !regexec(&regexbuf, ast_var_value(current), 0, NULL, 0)) {
ast_cli(fd, FORMAT_STRING, c->name, ast_var_value(current), "(default)");
numchans++;
}
}
}
numchans++;
ast_mutex_unlock(&c->lock);
}
if (havepattern)
regfree(&regexbuf);
ast_cli(fd, "%d active channel%s\n", numchans, (numchans != 1) ? "s" : "");
return RESULT_SUCCESS;
#undef FORMAT_STRING
}
static char *tdesc = "Group Management Routines";
static char *app_group_count = "GetGroupCount";
static char *app_group_set = "SetGroup";
static char *app_group_check = "CheckGroup";
static char *app_group_match_count = "GetGroupMatchCount";
static char *group_count_synopsis = "Get the channel count of a group";
static char *group_set_synopsis = "Set the channel's group";
static char *group_check_synopsis = "Check the channel count of a group against a limit";
static char *group_match_count_synopsis = "Get the channel count of all groups that match a pattern";
static char *group_count_descrip =
"Usage: GetGroupCount([groupname][@category])\n"
" Calculates the group count for the specified group, or uses\n"
"the current channel's group if not specifed (and non-empty).\n"
"Stores result in GROUPCOUNT. \n"
"Note: This application has been deprecated, please use the function\n"
"GROUP_COUNT.\n";
static char *group_set_descrip =
"Usage: SetGroup(groupname[@category])\n"
" Sets the channel group to the specified value. Equivalent to\n"
"Set(GROUP=group). Always returns 0.\n";
static char *group_check_descrip =
"Usage: CheckGroup(max[@category][|options])\n"
" Checks that the current number of total channels in the\n"
"current channel's group does not exceed 'max'. If the number\n"
"does not exceed 'max', we continue to the next step. \n"
" The option string may contain zero of the following character:\n"
" 'j' -- jump to n+101 priority if the number does in fact exceed max,\n"
" and priority n+101 exists. Execuation then continues at that\n"
" step, otherwise -1 is returned.\n"
" This application sets the following channel variable upon successful completion:\n"
" CHECKGROUPSTATUS The status of the check that the current channel's\n"
" group does not exceed 'max'. It's value is one of\n"
" OK | OVERMAX \n";
static char *group_match_count_descrip =
"Usage: GetGroupMatchCount(groupmatch[@category])\n"
" Calculates the group count for all groups that match the specified\n"
"pattern. Uses standard regular expression matching (see regex(7)).\n"
"Stores result in GROUPCOUNT. Always returns 0.\n"
"Note: This application has been deprecated, please use the function\n"
"GROUP_MATCH_COUNT.\n";
static char show_channels_usage[] =
"Usage: group show channels [pattern]\n"
" Lists all currently active channels with channel group(s) specified.\n Optional regular expression pattern is matched to group names for each channel.\n";
static struct ast_cli_entry cli_show_channels =
{ { "group", "show", "channels", NULL }, group_show_channels, "Show active channels with group(s)", show_channels_usage};
int unload_module(void)
{
int res;
res = ast_cli_unregister(&cli_show_channels);
res |= ast_unregister_application(app_group_count);
res |= ast_unregister_application(app_group_set);
res |= ast_unregister_application(app_group_check);
res |= ast_unregister_application(app_group_match_count);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
int load_module(void)
{
int res;
res = ast_register_application(app_group_count, group_count_exec, group_count_synopsis, group_count_descrip);
res |= ast_register_application(app_group_set, group_set_exec, group_set_synopsis, group_set_descrip);
res |= ast_register_application(app_group_check, group_check_exec, group_check_synopsis, group_check_descrip);
res |= ast_register_application(app_group_match_count, group_match_count_exec, group_match_count_synopsis, group_match_count_descrip);
res |= ast_cli_register(&cli_show_channels);
return res;
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,7 +1,7 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Changes Copyright (c) 2004 - 2006 Todd Freeman <freeman@andrews.edu>
* Changes Copyright (c) 2004 - 2005 Todd Freeman <freeman@andrews.edu>
*
* 95% based on HasNewVoicemail by:
*
@@ -24,18 +24,9 @@
*
* \brief HasVoicemail application
*
* \author Todd Freeman <freeman@andrews.edu>
*
* \note 95% based on HasNewVoicemail by
* Tilghman Lesher <asterisk-hasnewvoicemail-app@the-tilghman.com>
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -43,6 +34,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <dirent.h>
#include <sys/types.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
@@ -53,6 +48,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/app.h"
#include "asterisk/options.h"
static char *tdesc = "Indicator for whether a voice mailbox has messages in a given folder.";
static char *app_hasvoicemail = "HasVoicemail";
static char *hasvoicemail_synopsis = "Conditionally branches to priority + 101 with the right options set";
static char *hasvoicemail_descrip =
@@ -63,8 +59,7 @@ static char *hasvoicemail_descrip =
" 'j' -- jump to priority n+101, if there is voicemail in the folder indicated.\n"
" This application sets the following channel variable upon completion:\n"
" HASVMSTATUS The result of the voicemail check returned as a text string as follows\n"
" <# of messages in the folder, 0 for NONE>\n"
"\nThis application has been deprecated in favor of the VMCOUNT() function\n";
" <# of messages in the folder, 0 for NONE>\n";
static char *app_hasnewvoicemail = "HasNewVoicemail";
static char *hasnewvoicemail_synopsis = "Conditionally branches to priority + 101 with the right options set";
@@ -76,13 +71,35 @@ static char *hasnewvoicemail_descrip =
" 'j' -- jump to priority n+101, if there is new voicemail in folder 'folder' or INBOX\n"
" This application sets the following channel variable upon completion:\n"
" HASVMSTATUS The result of the new voicemail check returned as a text string as follows\n"
" <# of messages in the folder, 0 for NONE>\n"
"\nThis application has been deprecated in favor of the VMCOUNT() function\n";
" <# of messages in the folder, 0 for NONE>\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int hasvoicemail_internal(char *context, char *box, char *folder)
{
char vmpath[256];
DIR *vmdir;
struct dirent *vment;
int count=0;
snprintf(vmpath,sizeof(vmpath), "%s/voicemail/%s/%s/%s", (char *)ast_config_AST_SPOOL_DIR, context, box, folder);
if ((vmdir = opendir(vmpath))) {
/* No matter what the format of VM, there will always be a .txt file for each message. */
while ((vment = readdir(vmdir))) {
if (!strncmp(vment->d_name + 7, ".txt", 4)) {
count++;
}
}
closedir(vmdir);
}
return count;
}
static int hasvoicemail_exec(struct ast_channel *chan, void *data)
{
struct ast_module_user *u;
struct localuser *u;
char *input, *varname = NULL, *vmbox, *context = "default";
char *vmfolder;
int vmcount = 0;
@@ -105,16 +122,22 @@ static int hasvoicemail_exec(struct ast_channel *chan, void *data)
return -1;
}
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
input = ast_strdupa(data);
input = ast_strdupa((char *)data);
if (! input) {
ast_log(LOG_ERROR, "Out of memory error\n");
LOCAL_USER_REMOVE(u);
return -1;
}
AST_STANDARD_APP_ARGS(args, input);
vmbox = strsep(&args.vmbox, "@");
if (!ast_strlen_zero(args.vmbox))
context = args.vmbox;
if ((vmbox = strsep(&args.vmbox, "@")))
if (!ast_strlen_zero(args.vmbox))
context = args.vmbox;
if (!vmbox)
vmbox = args.vmbox;
vmfolder = strchr(vmbox, '/');
if (vmfolder) {
@@ -129,7 +152,7 @@ static int hasvoicemail_exec(struct ast_channel *chan, void *data)
priority_jump = 1;
}
vmcount = ast_app_messagecount(context, vmbox, vmfolder);
vmcount = hasvoicemail_internal(context, vmbox, vmfolder);
/* Set the count in the channel variable */
if (varname) {
snprintf(tmp, sizeof(tmp), "%d", vmcount);
@@ -138,7 +161,7 @@ static int hasvoicemail_exec(struct ast_channel *chan, void *data)
if (vmcount > 0) {
/* Branch to the next extension */
if (priority_jump || ast_opt_priority_jumping) {
if (priority_jump || option_priority_jumping) {
if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101))
ast_log(LOG_WARNING, "VM box %s@%s has new voicemail, but extension %s, priority %d doesn't exist\n", vmbox, context, chan->exten, chan->priority + 101);
}
@@ -147,45 +170,46 @@ static int hasvoicemail_exec(struct ast_channel *chan, void *data)
snprintf(tmp, sizeof(tmp), "%d", vmcount);
pbx_builtin_setvar_helper(chan, "HASVMSTATUS", tmp);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return 0;
}
static int acf_vmcount_exec(struct ast_channel *chan, char *cmd, char *argsstr, char *buf, size_t len)
static char *acf_vmcount_exec(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
{
struct ast_module_user *u;
char *context;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(vmbox);
AST_APP_ARG(folder);
);
struct localuser *u;
char *args, *context, *box, *folder;
if (ast_strlen_zero(argsstr))
return -1;
u = ast_module_user_add(chan);
LOCAL_USER_ACF_ADD(u);
buf[0] = '\0';
AST_STANDARD_APP_ARGS(args, argsstr);
args = ast_strdupa(data);
if (!args) {
ast_log(LOG_ERROR, "Out of memory");
LOCAL_USER_REMOVE(u);
return buf;
}
if (strchr(args.vmbox, '@')) {
context = args.vmbox;
args.vmbox = strsep(&context, "@");
box = strsep(&args, "|");
if (strchr(box, '@')) {
context = box;
box = strsep(&context, "@");
} else {
context = "default";
}
if (ast_strlen_zero(args.folder)) {
args.folder = "INBOX";
if (args) {
folder = args;
} else {
folder = "INBOX";
}
snprintf(buf, len, "%d", ast_app_messagecount(context, args.vmbox, args.folder));
snprintf(buf, len, "%d", hasvoicemail_internal(context, box, folder));
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return 0;
return buf;
}
struct ast_custom_function acf_vmcount = {
@@ -198,7 +222,7 @@ struct ast_custom_function acf_vmcount = {
.read = acf_vmcount_exec,
};
static int unload_module(void)
int unload_module(void)
{
int res;
@@ -206,12 +230,12 @@ static int unload_module(void)
res |= ast_unregister_application(app_hasvoicemail);
res |= ast_unregister_application(app_hasnewvoicemail);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
int res;
@@ -222,4 +246,19 @@ static int load_module(void)
return res;
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Indicator for whether a voice mailbox has messages in a given folder.");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,20 +19,10 @@
/*! \file
*
* \brief Stream to an icecast server via ICES (see contrib/asterisk-ices.xml)
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
/*** MODULEINFO
<depend>working_fork</depend>
***/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <string.h>
#include <stdio.h>
#include <signal.h>
@@ -41,9 +31,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <fcntl.h>
#include <sys/time.h>
#include <errno.h>
#ifdef HAVE_CAP
#include <sys/capability.h>
#endif /* HAVE_CAP */
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
@@ -53,10 +44,11 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/options.h"
#define path_BIN "/usr/bin/"
#define path_LOCAL "/usr/local/bin/"
#define ICES "/usr/bin/ices"
#define LOCAL_ICES "/usr/local/bin/ices"
static char *tdesc = "Encode and Stream via icecast and ices";
static char *app = "ICES";
@@ -65,74 +57,40 @@ static char *synopsis = "Encode and stream using 'ices'";
static char *descrip =
" ICES(config.xml) Streams to an icecast server using ices\n"
"(available separately). A configuration file must be supplied\n"
"for ices (see contrib/asterisk-ices.xml). \n";
"for ices (see examples/asterisk-ices.conf). \n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int icesencode(char *filename, int fd)
{
int res;
int x;
sigset_t fullset, oldset;
#ifdef HAVE_CAP
cap_t cap;
#endif
sigfillset(&fullset);
pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
res = fork();
if (res < 0)
ast_log(LOG_WARNING, "Fork failed\n");
if (res) {
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
if (res)
return res;
}
/* Stop ignoring PIPE */
signal(SIGPIPE, SIG_DFL);
pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
#ifdef HAVE_CAP
cap = cap_from_text("cap_net_admin-eip");
if (cap_set_proc(cap)) {
/* Careful with order! Logging cannot happen after we close FDs */
ast_log(LOG_WARNING, "Unable to remove capabilities.\n");
}
cap_free(cap);
#endif
if (ast_opt_high_priority)
ast_set_priority(0);
dup2(fd, STDIN_FILENO);
for (x=STDERR_FILENO + 1;x<1024;x++) {
for (x=STDERR_FILENO + 1;x<256;x++) {
if ((x != STDIN_FILENO) && (x != STDOUT_FILENO))
close(x);
}
/* Most commonly installed in /usr/local/bin
* But many places has it in /usr/bin
* As a last-ditch effort, try to use PATH
*/
execl(path_LOCAL "ices2", "ices", filename, (char *)NULL);
execl(path_BIN "ices2", "ices", filename, (char *)NULL);
execlp("ices2", "ices", filename, (char *)NULL);
if (option_debug)
ast_log(LOG_DEBUG, "Couldn't find ices version 2, attempting to use ices version 1.");
execl(path_LOCAL "ices", "ices", filename, (char *)NULL);
execl(path_BIN "ices", "ices", filename, (char *)NULL);
/* Most commonly installed in /usr/local/bin */
execl(ICES, "ices", filename, (char *)NULL);
/* But many places has it in /usr/bin */
execl(LOCAL_ICES, "ices", filename, (char *)NULL);
/* As a last-ditch effort, try to use PATH */
execlp("ices", "ices", filename, (char *)NULL);
ast_log(LOG_WARNING, "Execute of ices failed, could not be found.\n");
close(fd);
_exit(0);
ast_log(LOG_WARNING, "Execute of ices failed\n");
return -1;
}
static int ices_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct ast_module_user *u;
struct localuser *u;
int fds[2];
int ms = -1;
int pid = -1;
@@ -148,13 +106,13 @@ static int ices_exec(struct ast_channel *chan, void *data)
return -1;
}
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
last = ast_tv(0, 0);
if (pipe(fds)) {
ast_log(LOG_WARNING, "Unable to create pipe\n");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
flags = fcntl(fds[1], F_GETFL);
@@ -169,7 +127,7 @@ static int ices_exec(struct ast_channel *chan, void *data)
close(fds[0]);
close(fds[1]);
ast_log(LOG_WARNING, "Answer failed!\n");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
@@ -179,11 +137,11 @@ static int ices_exec(struct ast_channel *chan, void *data)
close(fds[0]);
close(fds[1]);
ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
if (((char *)data)[0] == '/')
ast_copy_string(filename, (char *) data, sizeof(filename));
strncpy(filename, (char *)data, sizeof(filename) - 1);
else
snprintf(filename, sizeof(filename), "%s/%s", (char *)ast_config_AST_CONFIG_DIR, (char *)data);
/* Placeholder for options */
@@ -191,6 +149,7 @@ static int ices_exec(struct ast_channel *chan, void *data)
if (c)
*c = '\0';
res = icesencode(filename, fds[0]);
close(fds[0]);
if (res >= 0) {
pid = res;
for (;;) {
@@ -213,7 +172,6 @@ static int ices_exec(struct ast_channel *chan, void *data)
if (errno != EAGAIN) {
ast_log(LOG_WARNING, "Write failed to pipe: %s\n", strerror(errno));
res = -1;
ast_frfree(f);
break;
}
}
@@ -221,7 +179,6 @@ static int ices_exec(struct ast_channel *chan, void *data)
ast_frfree(f);
}
}
close(fds[0]);
close(fds[1]);
if (pid > -1)
@@ -229,25 +186,40 @@ static int ices_exec(struct ast_channel *chan, void *data)
if (!res && oreadformat)
ast_set_read_format(chan, oreadformat);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, ices_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Encode and Stream via icecast and ices");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,20 +19,18 @@
/*! \file
*
* \brief App to transmit an image
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
@@ -44,6 +42,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/app.h"
#include "asterisk/options.h"
static char *tdesc = "Image Transmission Application";
static char *app = "SendImage";
static char *synopsis = "Send an image file";
@@ -59,11 +59,14 @@ static char *descrip =
" SENDIMAGESTATUS The status is the result of the attempt as a text string, one of\n"
" OK | NOSUPPORT \n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int sendimage_exec(struct ast_channel *chan, void *data)
{
int res = 0;
struct ast_module_user *u;
struct localuser *u;
char *parse;
int priority_jump = 0;
AST_DECLARE_APP_ARGS(args,
@@ -71,9 +74,13 @@ static int sendimage_exec(struct ast_channel *chan, void *data)
AST_APP_ARG(options);
);
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
parse = ast_strdupa(data);
if (!(parse = ast_strdupa(data))) {
ast_log(LOG_WARNING, "Memory Error!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
AST_STANDARD_APP_ARGS(args, parse);
@@ -89,10 +96,10 @@ static int sendimage_exec(struct ast_channel *chan, void *data)
if (!ast_supports_images(chan)) {
/* Does not support transport */
if (priority_jump || ast_opt_priority_jumping)
if (priority_jump || option_priority_jumping)
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
pbx_builtin_setvar_helper(chan, "SENDIMAGESTATUS", "NOSUPPORT");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return 0;
}
@@ -101,25 +108,40 @@ static int sendimage_exec(struct ast_channel *chan, void *data)
if (!res)
pbx_builtin_setvar_helper(chan, "SENDIMAGESTATUS", "OK");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, sendimage_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Image Transmission Application");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

234
apps/app_intercom.c Normal file
View File

@@ -0,0 +1,234 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2005, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief Use /dev/dsp as an intercom.
*
* \ingroup applications
*/
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <string.h>
#include <stdlib.h>
#include <sys/time.h>
#include <netinet/in.h>
#if defined(__linux__)
#include <linux/soundcard.h>
#elif defined(__FreeBSD__)
#include <sys/soundcard.h>
#else
#include <soundcard.h>
#endif
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/frame.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#ifdef __OpenBSD__
#define DEV_DSP "/dev/audio"
#else
#define DEV_DSP "/dev/dsp"
#endif
/* Number of 32 byte buffers -- each buffer is 2 ms */
#define BUFFER_SIZE 32
static char *tdesc = "Intercom using /dev/dsp for output";
static char *app = "Intercom";
static char *synopsis = "(Obsolete) Send to Intercom";
static char *descrip =
" Intercom(): Sends the user to the intercom (i.e. /dev/dsp). This program\n"
"is generally considered obselete by the chan_oss module. User can terminate\n"with a DTMF tone, or by hangup.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
AST_MUTEX_DEFINE_STATIC(sound_lock);
static int sound = -1;
static int write_audio(short *data, int len)
{
int res;
struct audio_buf_info info;
ast_mutex_lock(&sound_lock);
if (sound < 0) {
ast_log(LOG_WARNING, "Sound device closed?\n");
ast_mutex_unlock(&sound_lock);
return -1;
}
if (ioctl(sound, SNDCTL_DSP_GETOSPACE, &info)) {
ast_log(LOG_WARNING, "Unable to read output space\n");
ast_mutex_unlock(&sound_lock);
return -1;
}
res = write(sound, data, len);
ast_mutex_unlock(&sound_lock);
return res;
}
static int create_audio(void)
{
int fmt, desired, res, fd;
fd = open(DEV_DSP, O_WRONLY);
if (fd < 0) {
ast_log(LOG_WARNING, "Unable to open %s: %s\n", DEV_DSP, strerror(errno));
close(fd);
return -1;
}
fmt = AFMT_S16_LE;
res = ioctl(fd, SNDCTL_DSP_SETFMT, &fmt);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set format to 16-bit signed\n");
close(fd);
return -1;
}
fmt = 0;
res = ioctl(fd, SNDCTL_DSP_STEREO, &fmt);
if (res < 0) {
ast_log(LOG_WARNING, "Failed to set audio device to mono\n");
close(fd);
return -1;
}
/* 8000 Hz desired */
desired = 8000;
fmt = desired;
res = ioctl(fd, SNDCTL_DSP_SPEED, &fmt);
if (res < 0) {
ast_log(LOG_WARNING, "Failed to set audio device to mono\n");
close(fd);
return -1;
}
if (fmt != desired) {
ast_log(LOG_WARNING, "Requested %d Hz, got %d Hz -- sound may be choppy\n", desired, fmt);
}
#if 1
/* 2 bytes * 15 units of 2^5 = 32 bytes per buffer */
fmt = ((BUFFER_SIZE) << 16) | (0x0005);
res = ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &fmt);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set fragment size -- sound may be choppy\n");
}
#endif
sound = fd;
return 0;
}
static int intercom_exec(struct ast_channel *chan, void *data)
{
int res = 0;
struct localuser *u;
struct ast_frame *f;
int oreadformat;
LOCAL_USER_ADD(u);
/* Remember original read format */
oreadformat = chan->readformat;
/* Set mode to signed linear */
res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set format to signed linear on channel %s\n", chan->name);
LOCAL_USER_REMOVE(u);
return -1;
}
/* Read packets from the channel */
while(!res) {
res = ast_waitfor(chan, -1);
if (res > 0) {
res = 0;
f = ast_read(chan);
if (f) {
if (f->frametype == AST_FRAME_DTMF) {
ast_frfree(f);
break;
} else {
if (f->frametype == AST_FRAME_VOICE) {
if (f->subclass == AST_FORMAT_SLINEAR) {
res = write_audio(f->data, f->datalen);
if (res > 0)
res = 0;
} else
ast_log(LOG_DEBUG, "Unable to handle non-signed linear frame (%d)\n", f->subclass);
}
}
ast_frfree(f);
} else
res = -1;
}
}
if (!res)
ast_set_read_format(chan, oreadformat);
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
int res;
if (sound > -1)
close(sound);
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
int load_module(void)
{
if (create_audio())
return -1;
return ast_register_application(app, intercom_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,25 +19,19 @@
/*! \file
*
* \brief IVR Demo application
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
/*** MODULEINFO
<defaultenabled>no</defaultenabled>
***/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
@@ -88,18 +82,21 @@ AST_IVR_DECLARE_MENU(ivr_demo, "IVR Demo Main Menu", 0,
{ NULL },
});
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int skel_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct ast_module_user *u;
struct localuser *u;
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "skel requires an argument (filename)\n");
return -1;
}
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
/* Do our thing here */
@@ -108,25 +105,40 @@ static int skel_exec(struct ast_channel *chan, void *data)
if (!res)
res = ast_ivr_menu_run(chan, &ivr_demo, data);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, skel_exec, tdesc, synopsis);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "IVR Demo Application");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -20,20 +20,18 @@
*
* \brief App to lookup the callerid number, and see if it is blacklisted
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
@@ -47,6 +45,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/astdb.h"
#include "asterisk/options.h"
static char *tdesc = "Look up Caller*ID name/number from blacklist database";
static char *app = "LookupBlacklist";
static char *synopsis = "Look up Caller*ID name/number from blacklist database";
@@ -59,52 +59,21 @@ static char *descrip =
"This application sets the following channel variable upon completion:\n"
" LOOKUPBLSTATUS The status of the Blacklist lookup as a text string, one of\n"
" FOUND | NOTFOUND\n"
"Example: exten => 1234,1,LookupBlacklist()\n\n"
"This application is deprecated and may be removed from a future release.\n"
"Please use the dialplan function BLACKLIST() instead.\n";
"Example: exten => 1234,1,LookupBlacklist()\n";
STANDARD_LOCAL_USER;
static int blacklist_read(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
{
char blacklist[1];
int bl = 0;
if (chan->cid.cid_num) {
if (!ast_db_get("blacklist", chan->cid.cid_num, blacklist, sizeof (blacklist)))
bl = 1;
}
if (chan->cid.cid_name) {
if (!ast_db_get("blacklist", chan->cid.cid_name, blacklist, sizeof (blacklist)))
bl = 1;
}
snprintf(buf, len, "%d", bl);
return 0;
}
static struct ast_custom_function blacklist_function = {
.name = "BLACKLIST",
.synopsis = "Check if the callerid is on the blacklist",
.desc = "Uses astdb to check if the Caller*ID is in family 'blacklist'. Returns 1 or 0.\n",
.syntax = "BLACKLIST()",
.read = blacklist_read,
};
LOCAL_USER_DECL;
static int
lookupblacklist_exec (struct ast_channel *chan, void *data)
{
char blacklist[1];
struct ast_module_user *u;
struct localuser *u;
int bl = 0;
int priority_jump = 0;
static int dep_warning = 0;
u = ast_module_user_add(chan);
if (!dep_warning) {
dep_warning = 1;
ast_log(LOG_WARNING, "LookupBlacklist is deprecated. Please use ${BLACKLIST()} instead.\n");
}
LOCAL_USER_ADD(u);
if (!ast_strlen_zero(data)) {
if (strchr(data, 'j'))
@@ -127,34 +96,46 @@ lookupblacklist_exec (struct ast_channel *chan, void *data)
}
if (bl) {
if (priority_jump || ast_opt_priority_jumping)
if (priority_jump || option_priority_jumping)
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
pbx_builtin_setvar_helper(chan, "LOOKUPBLSTATUS", "FOUND");
} else
pbx_builtin_setvar_helper(chan, "LOOKUPBLSTATUS", "NOTFOUND");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return 0;
}
static int unload_module(void)
int unload_module (void)
{
int res;
res = ast_unregister_application(app);
res |= ast_custom_function_unregister(&blacklist_function);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module (void)
{
int res = ast_custom_function_register(&blacklist_function);
res |= ast_register_application (app, lookupblacklist_exec, synopsis,descrip);
return ast_register_application (app, lookupblacklist_exec, synopsis,descrip);
}
char *description (void)
{
return tdesc;
}
int usecount (void)
{
int res;
STANDARD_USECOUNT (res);
return res;
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Look up Caller*ID name/number from blacklist database");
char *key ()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,20 +19,18 @@
/*! \file
*
* \brief App to set callerid name from database, based on directory number
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
@@ -45,6 +43,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/callerid.h"
#include "asterisk/astdb.h"
static char *tdesc = "Look up CallerID Name from local database";
static char *app = "LookupCIDName";
static char *synopsis = "Look up CallerID Name from local database";
@@ -55,49 +55,66 @@ static char *descrip =
"Caller*ID name. Does nothing if no Caller*ID was received on the\n"
"channel. This is useful if you do not subscribe to Caller*ID\n"
"name delivery, or if you want to change the names on some incoming\n"
"calls.\n\n"
"LookupCIDName is deprecated. Please use ${DB(cidname/${CALLERID(num)})}\n"
"instead.\n";
"calls.\n";
STANDARD_LOCAL_USER;
static int lookupcidname_exec (struct ast_channel *chan, void *data)
LOCAL_USER_DECL;
static int
lookupcidname_exec (struct ast_channel *chan, void *data)
{
char dbname[64];
struct ast_module_user *u;
static int dep_warning = 0;
char dbname[64];
struct localuser *u;
u = ast_module_user_add(chan);
if (!dep_warning) {
dep_warning = 1;
ast_log(LOG_WARNING, "LookupCIDName is deprecated. Please use ${DB(cidname/${CALLERID(num)})} instead.\n");
LOCAL_USER_ADD (u);
if (chan->cid.cid_num) {
if (!ast_db_get ("cidname", chan->cid.cid_num, dbname, sizeof (dbname))) {
ast_set_callerid (chan, NULL, dbname, NULL);
if (option_verbose > 2)
ast_verbose (VERBOSE_PREFIX_3 "Changed Caller*ID name to %s\n",
dbname);
}
if (chan->cid.cid_num) {
if (!ast_db_get ("cidname", chan->cid.cid_num, dbname, sizeof (dbname))) {
ast_set_callerid (chan, NULL, dbname, NULL);
if (option_verbose > 2)
ast_verbose (VERBOSE_PREFIX_3 "Changed Caller*ID name to %s\n",
dbname);
}
}
ast_module_user_remove(u);
return 0;
}
LOCAL_USER_REMOVE (u);
return 0;
}
static int unload_module(void)
int
unload_module (void)
{
int res;
res = ast_unregister_application (app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int
load_module (void)
{
return ast_register_application (app, lookupcidname_exec, synopsis, descrip);
return ast_register_application (app, lookupcidname_exec, synopsis,
descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Look up CallerID Name from local database");
char *
description (void)
{
return tdesc;
}
int
usecount (void)
{
int res;
STANDARD_USECOUNT (res);
return res;
}
char *
key ()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,22 +19,20 @@
/*! \file
*
* \brief Dial plan macro Implementation
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
@@ -50,6 +48,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
/* special result value used to force macro exit */
#define MACRO_EXIT_RESULT 1024
static char *tdesc = "Extension Macros";
static char *descrip =
" Macro(macroname|arg1|arg2...): Executes a macro using the context\n"
"'macro-<macroname>', jumping to the 's' extension of that context and\n"
@@ -60,18 +60,7 @@ static char *descrip =
"If you Goto out of the Macro context, the Macro will terminate and control\n"
"will be returned at the location of the Goto.\n"
"If ${MACRO_OFFSET} is set at termination, Macro will attempt to continue\n"
"at priority MACRO_OFFSET + N + 1 if such a step exists, and N + 1 otherwise.\n"
"Extensions: While a macro is being executed, it becomes the current context.\n"
" This means that if a hangup occurs, for instance, that the macro\n"
" will be searched for an 'h' extension, NOT the context from which\n"
" the macro was called. So, make sure to define all appropriate\n"
" extensions in your macro! (you can use 'catch' in AEL) \n"
"WARNING: Because of the way Macro is implemented (it executes the priorities\n"
" contained within it via sub-engine), and a fixed per-thread\n"
" memory stack allowance, macros are limited to 7 levels\n"
" of nesting (macro calling macro calling macro, etc.); It\n"
" may be possible that stack-intensive applications in deeply nested macros\n"
" could cause asterisk to crash earlier than this limit.\n";
"at priority MACRO_OFFSET + N + 1 if such a step exists, and N + 1 otherwise.\n";
static char *if_descrip =
" MacroIf(<expr>?macroname_a[|arg1][:macroname_b[|arg1]])\n"
@@ -79,13 +68,6 @@ static char *if_descrip =
"(otherwise <macroname_b> if provided)\n"
"Arguments and return values as in application macro()\n";
static char *exclusive_descrip =
" MacroExclusive(macroname|arg1|arg2...):\n"
"Executes macro defined in the context 'macro-macroname'\n"
"Only one call at a time may run the macro.\n"
"(we'll wait if another call is busy executing in the Macro)\n"
"Arguments and return values as in application Macro()\n";
static char *exit_descrip =
" MacroExit():\n"
"Causes the currently running macro to exit as if it had\n"
@@ -95,141 +77,59 @@ static char *exit_descrip =
static char *app = "Macro";
static char *if_app = "MacroIf";
static char *exclusive_app = "MacroExclusive";
static char *exit_app = "MacroExit";
static char *synopsis = "Macro Implementation";
static char *if_synopsis = "Conditional Macro Implementation";
static char *exclusive_synopsis = "Exclusive Macro Implementation";
static char *exit_synopsis = "Exit From Macro";
static void macro_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan);
STANDARD_LOCAL_USER;
struct ast_datastore_info macro_ds_info = {
.type = "MACRO",
.chan_fixup = macro_fixup,
};
LOCAL_USER_DECL;
static void macro_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
static int macro_exec(struct ast_channel *chan, void *data)
{
int i;
char varname[10];
pbx_builtin_setvar_helper(new_chan, "MACRO_DEPTH", "0");
pbx_builtin_setvar_helper(new_chan, "MACRO_CONTEXT", NULL);
pbx_builtin_setvar_helper(new_chan, "MACRO_EXTEN", NULL);
pbx_builtin_setvar_helper(new_chan, "MACRO_PRIORITY", NULL);
pbx_builtin_setvar_helper(new_chan, "MACRO_OFFSET", NULL);
for (i = 1; i < 100; i++) {
snprintf(varname, sizeof(varname), "ARG%d", i);
while (pbx_builtin_getvar_helper(new_chan, varname)) {
/* Kill all levels of arguments */
pbx_builtin_setvar_helper(new_chan, varname, NULL);
}
}
}
static struct ast_exten *find_matching_priority(struct ast_context *c, const char *exten, int priority, const char *callerid)
{
struct ast_exten *e;
struct ast_include *i;
struct ast_context *c2;
for (e=ast_walk_context_extensions(c, NULL); e; e=ast_walk_context_extensions(c, e)) {
if (ast_extension_match(ast_get_extension_name(e), exten)) {
int needmatch = ast_get_extension_matchcid(e);
if ((needmatch && ast_extension_match(ast_get_extension_cidmatch(e), callerid)) ||
(!needmatch)) {
/* This is the matching extension we want */
struct ast_exten *p;
for (p=ast_walk_extension_priorities(e, NULL); p; p=ast_walk_extension_priorities(e, p)) {
if (priority != ast_get_extension_priority(p))
continue;
return p;
}
}
}
}
/* No match; run through includes */
for (i=ast_walk_context_includes(c, NULL); i; i=ast_walk_context_includes(c, i)) {
for (c2=ast_walk_contexts(NULL); c2; c2=ast_walk_contexts(c2)) {
if (!strcmp(ast_get_context_name(c2), ast_get_include_name(i))) {
e = find_matching_priority(c2, exten, priority, callerid);
if (e)
return e;
}
}
}
return NULL;
}
static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
{
const char *s;
char *tmp;
char *cur, *rest;
char *macro;
char fullmacro[80];
char varname[80];
char runningapp[80], runningdata[1024];
char *oldargs[MAX_ARGS + 1] = { NULL, };
int argc, x;
int res=0;
char oldexten[256]="";
int oldpriority, gosub_level = 0;
int oldpriority;
char pc[80], depthc[12];
char oldcontext[AST_MAX_CONTEXT] = "";
const char *inhangupc;
int offset, depth = 0, maxdepth = 7;
char *offsets;
int offset, depth;
int setmacrocontext=0;
int autoloopflag, inhangup = 0;
int autoloopflag, dead = 0;
char *save_macro_exten;
char *save_macro_context;
char *save_macro_priority;
char *save_macro_offset;
struct ast_module_user *u;
struct ast_datastore *macro_store = ast_channel_datastore_find(chan, &macro_ds_info, NULL);
struct localuser *u;
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Macro() requires arguments. See \"show application macro\" for help.\n");
return -1;
}
u = ast_module_user_add(chan);
do {
if (macro_store) {
break;
}
if (!(macro_store = ast_channel_datastore_alloc(&macro_ds_info, NULL))) {
ast_log(LOG_WARNING, "Unable to allocate new datastore.\n");
break;
}
/* Just the existence of this datastore is enough. */
macro_store->inheritance = DATASTORE_INHERIT_FOREVER;
ast_channel_datastore_add(chan, macro_store);
} while (0);
/* does the user want a deeper rabbit hole? */
s = pbx_builtin_getvar_helper(chan, "MACRO_RECURSION");
if (s)
sscanf(s, "%d", &maxdepth);
LOCAL_USER_ADD(u);
/* Count how many levels deep the rabbit hole goes */
s = pbx_builtin_getvar_helper(chan, "MACRO_DEPTH");
if (s)
sscanf(s, "%d", &depth);
/* Used for detecting whether to return when a Macro is called from another Macro after hangup */
if (strcmp(chan->exten, "h") == 0)
pbx_builtin_setvar_helper(chan, "MACRO_IN_HANGUP", "1");
inhangupc = pbx_builtin_getvar_helper(chan, "MACRO_IN_HANGUP");
if (!ast_strlen_zero(inhangupc))
sscanf(inhangupc, "%d", &inhangup);
tmp = pbx_builtin_getvar_helper(chan, "MACRO_DEPTH");
if (tmp) {
sscanf(tmp, "%d", &depth);
} else {
depth = 0;
}
if (depth >= maxdepth) {
if (depth >= 7) {
ast_log(LOG_ERROR, "Macro(): possible infinite loop detected. Returning early.\n");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return 0;
}
snprintf(depthc, sizeof(depthc), "%d", depth + 1);
@@ -240,33 +140,18 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
macro = strsep(&rest, "|");
if (ast_strlen_zero(macro)) {
ast_log(LOG_WARNING, "Invalid macro name specified\n");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return 0;
}
snprintf(fullmacro, sizeof(fullmacro), "macro-%s", macro);
if (!ast_exists_extension(chan, fullmacro, "s", 1, chan->cid.cid_num)) {
if (!ast_context_find(fullmacro))
if (!ast_context_find(fullmacro))
ast_log(LOG_WARNING, "No such context '%s' for macro '%s'\n", fullmacro, macro);
else
ast_log(LOG_WARNING, "Context '%s' for macro '%s' lacks 's' extension, priority 1\n", fullmacro, macro);
ast_module_user_remove(u);
ast_log(LOG_WARNING, "Context '%s' for macro '%s' lacks 's' extension, priority 1\n", fullmacro, macro);
LOCAL_USER_REMOVE(u);
return 0;
}
/* If we are to run the macro exclusively, take the mutex */
if (exclusive) {
ast_log(LOG_DEBUG, "Locking macrolock for '%s'\n", fullmacro);
ast_autoservice_start(chan);
if (ast_context_lockmacro(fullmacro)) {
ast_log(LOG_WARNING, "Failed to lock macro '%s' as in-use\n", fullmacro);
ast_autoservice_stop(chan);
ast_module_user_remove(u);
return 0;
}
ast_autoservice_stop(chan);
}
/* Save old info */
oldpriority = chan->priority;
@@ -280,17 +165,25 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
}
argc = 1;
/* Save old macro variables */
save_macro_exten = ast_strdup(pbx_builtin_getvar_helper(chan, "MACRO_EXTEN"));
save_macro_exten = pbx_builtin_getvar_helper(chan, "MACRO_EXTEN");
if (save_macro_exten)
save_macro_exten = strdup(save_macro_exten);
pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", oldexten);
save_macro_context = ast_strdup(pbx_builtin_getvar_helper(chan, "MACRO_CONTEXT"));
save_macro_context = pbx_builtin_getvar_helper(chan, "MACRO_CONTEXT");
if (save_macro_context)
save_macro_context = strdup(save_macro_context);
pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", oldcontext);
save_macro_priority = ast_strdup(pbx_builtin_getvar_helper(chan, "MACRO_PRIORITY"));
save_macro_priority = pbx_builtin_getvar_helper(chan, "MACRO_PRIORITY");
if (save_macro_priority)
save_macro_priority = strdup(save_macro_priority);
snprintf(pc, sizeof(pc), "%d", oldpriority);
pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", pc);
save_macro_offset = ast_strdup(pbx_builtin_getvar_helper(chan, "MACRO_OFFSET"));
save_macro_offset = pbx_builtin_getvar_helper(chan, "MACRO_OFFSET");
if (save_macro_offset)
save_macro_offset = strdup(save_macro_offset);
pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", NULL);
/* Setup environment for new run */
@@ -300,49 +193,20 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
chan->priority = 1;
while((cur = strsep(&rest, "|")) && (argc < MAX_ARGS)) {
const char *s;
/* Save copy of old arguments if we're overwriting some, otherwise
let them pass through to the other macro */
snprintf(varname, sizeof(varname), "ARG%d", argc);
s = pbx_builtin_getvar_helper(chan, varname);
if (s)
oldargs[argc] = ast_strdup(s);
oldargs[argc] = pbx_builtin_getvar_helper(chan, varname);
if (oldargs[argc])
oldargs[argc] = strdup(oldargs[argc]);
pbx_builtin_setvar_helper(chan, varname, cur);
argc++;
}
autoloopflag = ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP);
ast_set_flag(chan, AST_FLAG_IN_AUTOLOOP);
while(ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
struct ast_context *c;
struct ast_exten *e;
runningapp[0] = '\0';
runningdata[0] = '\0';
/* What application will execute? */
if (ast_rdlock_contexts()) {
ast_log(LOG_WARNING, "Failed to lock contexts list\n");
} else {
for (c = ast_walk_contexts(NULL), e = NULL; c; c = ast_walk_contexts(c)) {
if (!strcmp(ast_get_context_name(c), chan->context)) {
if (ast_lock_context(c)) {
ast_log(LOG_WARNING, "Unable to lock context?\n");
} else {
e = find_matching_priority(c, chan->exten, chan->priority, chan->cid.cid_num);
if (e) { /* This will only be undefined for pbx_realtime, which is majorly broken. */
ast_copy_string(runningapp, ast_get_extension_app(e), sizeof(runningapp));
ast_copy_string(runningdata, ast_get_extension_app_data(e), sizeof(runningdata));
}
ast_unlock_context(c);
}
break;
}
}
}
ast_unlock_contexts();
/* Reset the macro depth, if it was changed in the last iteration */
pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc);
if ((res = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num))) {
/* Something bad happened, or a hangup has been requested. */
if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
@@ -361,109 +225,56 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
else if (option_verbose > 1)
ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE in macro '%s' on '%s'\n", chan->context, chan->exten, chan->priority, macro, chan->name);
goto out;
break;
default:
if (option_debug)
ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s' in macro '%s'\n", chan->context, chan->exten, chan->priority, chan->name, macro);
else if (option_verbose > 1)
ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s' in macro '%s'\n", chan->context, chan->exten, chan->priority, chan->name, macro);
dead = 1;
goto out;
}
}
ast_log(LOG_DEBUG, "Executed application: %s\n", runningapp);
if (!strcasecmp(runningapp, "GOSUB")) {
gosub_level++;
ast_log(LOG_DEBUG, "Incrementing gosub_level\n");
} else if (!strcasecmp(runningapp, "GOSUBIF")) {
char tmp2[1024] = "", *cond, *app, *app2 = tmp2;
pbx_substitute_variables_helper(chan, runningdata, tmp2, sizeof(tmp2) - 1);
cond = strsep(&app2, "?");
app = strsep(&app2, ":");
if (pbx_checkcondition(cond)) {
if (!ast_strlen_zero(app)) {
gosub_level++;
ast_log(LOG_DEBUG, "Incrementing gosub_level\n");
}
} else {
if (!ast_strlen_zero(app2)) {
gosub_level++;
ast_log(LOG_DEBUG, "Incrementing gosub_level\n");
}
}
} else if (!strcasecmp(runningapp, "RETURN")) {
gosub_level--;
ast_log(LOG_DEBUG, "Decrementing gosub_level\n");
} else if (!strcasecmp(runningapp, "STACKPOP")) {
gosub_level--;
ast_log(LOG_DEBUG, "Decrementing gosub_level\n");
} else if (!strncasecmp(runningapp, "EXEC", 4)) {
/* Must evaluate args to find actual app */
char tmp2[1024] = "", *tmp3 = NULL;
pbx_substitute_variables_helper(chan, runningdata, tmp2, sizeof(tmp2) - 1);
if (!strcasecmp(runningapp, "EXECIF")) {
tmp3 = strchr(tmp2, '|');
if (tmp3)
*tmp3++ = '\0';
if (!pbx_checkcondition(tmp2))
tmp3 = NULL;
} else
tmp3 = tmp2;
if (tmp3)
ast_log(LOG_DEBUG, "Last app: %s\n", tmp3);
if (tmp3 && !strncasecmp(tmp3, "GOSUB", 5)) {
gosub_level++;
ast_log(LOG_DEBUG, "Incrementing gosub_level\n");
} else if (tmp3 && !strncasecmp(tmp3, "RETURN", 6)) {
gosub_level--;
ast_log(LOG_DEBUG, "Decrementing gosub_level\n");
} else if (tmp3 && !strncasecmp(tmp3, "STACKPOP", 8)) {
gosub_level--;
ast_log(LOG_DEBUG, "Decrementing gosub_level\n");
}
}
if (gosub_level == 0 && strcasecmp(chan->context, fullmacro)) {
if (strcasecmp(chan->context, fullmacro)) {
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "Channel '%s' jumping out of macro '%s'\n", chan->name, macro);
break;
}
/* don't stop executing extensions when we're in "h" */
if (chan->_softhangup && !inhangup) {
ast_log(LOG_DEBUG, "Extension %s, macroexten %s, priority %d returned normally even though call was hung up\n",
chan->exten, chan->macroexten, chan->priority);
if (chan->_softhangup && strcasecmp(oldexten,"h")) {
ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
chan->exten, chan->priority);
goto out;
}
chan->priority++;
}
out:
/* Don't let the channel change now. */
ast_channel_lock(chan);
/* Reset the depth back to what it was when the routine was entered (like if we called Macro recursively) */
snprintf(depthc, sizeof(depthc), "%d", depth);
pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc);
ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP);
if (!dead) {
pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc);
ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP);
}
for (x = 1; x < argc; x++) {
/* Restore old arguments and delete ours */
snprintf(varname, sizeof(varname), "ARG%d", x);
if (oldargs[x]) {
pbx_builtin_setvar_helper(chan, varname, oldargs[x]);
if (!dead)
pbx_builtin_setvar_helper(chan, varname, oldargs[x]);
free(oldargs[x]);
} else {
} else if (!dead) {
pbx_builtin_setvar_helper(chan, varname, NULL);
}
}
/* Restore macro variables */
pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", save_macro_exten);
pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", save_macro_context);
pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", save_macro_priority);
if (!dead) {
pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", save_macro_exten);
pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", save_macro_context);
pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", save_macro_priority);
}
if (save_macro_exten)
free(save_macro_exten);
if (save_macro_context)
@@ -471,36 +282,18 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
if (save_macro_priority)
free(save_macro_priority);
if (setmacrocontext) {
if (!dead && setmacrocontext) {
chan->macrocontext[0] = '\0';
chan->macroexten[0] = '\0';
chan->macropriority = 0;
}
/*!\note
* This section is used to restore a behavior that we mistakenly
* changed in issue #6176, then mistakenly reverted in #13962 and
* #13363. A corresponding change is made in main/pbx.c, where we
* check this variable for existence, then look for the "h" extension
* in that context.
*/
if (ast_check_hangup(chan) || res < 0) {
/* Don't need to lock the channel, as we aren't dereferencing emc.
* The intent here is to grab the deepest context, without overwriting
* in any above context. */
const char *emc = pbx_builtin_getvar_helper(chan, "EXIT_MACRO_CONTEXT");
if (!emc) {
pbx_builtin_setvar_helper(chan, "EXIT_MACRO_CONTEXT", fullmacro);
}
}
if (!strcasecmp(chan->context, fullmacro)) {
if (!dead && !strcasecmp(chan->context, fullmacro)) {
/* If we're leaving the macro normally, restore original information */
chan->priority = oldpriority;
ast_copy_string(chan->context, oldcontext, sizeof(chan->context));
if (!(chan->_softhangup & AST_SOFTHANGUP_ASYNCGOTO)) {
/* Copy the extension, so long as we're not in softhangup, where we could be given an asyncgoto */
const char *offsets;
ast_copy_string(chan->exten, oldexten, sizeof(chan->exten));
if ((offsets = pbx_builtin_getvar_helper(chan, "MACRO_OFFSET"))) {
/* Handle macro offset if it's set by checking the availability of step n + offset + 1, otherwise continue
@@ -514,45 +307,26 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
}
}
pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", save_macro_offset);
if (!dead)
pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", save_macro_offset);
if (save_macro_offset)
free(save_macro_offset);
/* Unlock the macro */
if (exclusive) {
ast_log(LOG_DEBUG, "Unlocking macrolock for '%s'\n", fullmacro);
if (ast_context_unlockmacro(fullmacro)) {
ast_log(LOG_ERROR, "Failed to unlock macro '%s' - that isn't good\n", fullmacro);
res = 0;
}
}
ast_channel_unlock(chan);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return res;
}
static int macro_exec(struct ast_channel *chan, void *data)
{
return _macro_exec(chan, data, 0);
}
static int macroexclusive_exec(struct ast_channel *chan, void *data)
{
return _macro_exec(chan, data, 1);
}
static int macroif_exec(struct ast_channel *chan, void *data)
{
char *expr = NULL, *label_a = NULL, *label_b = NULL;
int res = 0;
struct ast_module_user *u;
struct localuser *u;
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
if (!(expr = ast_strdupa(data))) {
ast_module_user_remove(u);
expr = ast_strdupa(data);
if (!expr) {
ast_log(LOG_ERROR, "Out of Memory!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
@@ -563,14 +337,14 @@ static int macroif_exec(struct ast_channel *chan, void *data)
*label_b = '\0';
label_b++;
}
if (pbx_checkcondition(expr))
res = macro_exec(chan, label_a);
if (ast_true(expr))
macro_exec(chan, label_a);
else if (label_b)
res = macro_exec(chan, label_b);
macro_exec(chan, label_b);
} else
ast_log(LOG_WARNING, "Invalid Syntax.\n");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return res;
}
@@ -580,30 +354,43 @@ static int macro_exit_exec(struct ast_channel *chan, void *data)
return MACRO_EXIT_RESULT;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(if_app);
res |= ast_unregister_application(exit_app);
res |= ast_unregister_application(app);
res |= ast_unregister_application(exclusive_app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
int res;
res = ast_register_application(exit_app, macro_exit_exec, exit_synopsis, exit_descrip);
res |= ast_register_application(if_app, macroif_exec, if_synopsis, if_descrip);
res |= ast_register_application(exclusive_app, macroexclusive_exec, exclusive_synopsis, exclusive_descrip);
res |= ast_register_application(app, macro_exec, synopsis, descrip);
return res;
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Extension Macros");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

297
apps/app_math.c Normal file
View File

@@ -0,0 +1,297 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2004 - 2005, Andy Powell
*
* Updated by Mark Spencer <markster@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief A simple math application
*
* \ingroup applications
*/
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <dirent.h>
#include <ctype.h>
#include <sys/file.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/config.h"
#include "asterisk/say.h"
#include "asterisk/module.h"
#include "asterisk/app.h"
#include "asterisk/manager.h"
#include "asterisk/localtime.h"
#include "asterisk/cli.h"
#include "asterisk/utils.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
static char *tdesc = "Basic Math Functions";
static char *app_math = "Math";
static char *math_synopsis = "Performs Mathematical Functions";
static char *math_descrip =
"Math(returnvar,<number1><op><number 2>\n\n"
"Perform floating point calculation on number 1 to number 2 and \n"
"store the result in returnvar. Valid ops are: \n"
" +,-,/,*,%,<,>,>=,<=,==\n"
"and behave as their C equivalents.\n";
#define ADDFUNCTION 0
#define DIVIDEFUNCTION 1
#define MULTIPLYFUNCTION 2
#define SUBTRACTFUNCTION 3
#define MODULUSFUNCTION 4
#define GTFUNCTION 5
#define LTFUNCTION 6
#define GTEFUNCTION 7
#define LTEFUNCTION 8
#define EQFUNCTION 9
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int math_exec(struct ast_channel *chan, void *data)
{
float fnum1;
float fnum2;
float ftmp = 0;
char *op;
int iaction=-1;
static int deprecation_warning = 0;
/* dunno, big calulations :D */
char user_result[30];
char *s;
char *mvar, *mvalue1, *mvalue2=NULL;
struct localuser *u;
if (!deprecation_warning) {
ast_log(LOG_WARNING, "Math() is deprecated, please use Set(var=${MATH(...)} instead.\n");
deprecation_warning = 1;
}
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "No parameters passed. !\n");
return -1;
}
LOCAL_USER_ADD(u);
s = ast_strdupa(data);
if (!s) {
ast_log(LOG_ERROR, "Out of memory\n");
LOCAL_USER_REMOVE(u);
return -1;
}
mvar = strsep(&s, "|");
mvalue1 = strsep(&s, "|");
if ((op = strchr(mvalue1, '+'))) {
iaction = ADDFUNCTION;
*op = '\0';
} else if ((op = strchr(mvalue1, '-'))) {
iaction = SUBTRACTFUNCTION;
*op = '\0';
} else if ((op = strchr(mvalue1, '*'))) {
iaction = MULTIPLYFUNCTION;
*op = '\0';
} else if ((op = strchr(mvalue1, '/'))) {
iaction = DIVIDEFUNCTION;
*op = '\0';
} else if ((op = strchr(mvalue1, '>'))) {
iaction = GTFUNCTION;
*op = '\0';
if (*(op+1) == '=') {
op++;
*op = '\0';
iaction = GTEFUNCTION;
}
} else if ((op = strchr(mvalue1, '<'))) {
iaction = LTFUNCTION;
*op = '\0';
if (*(op+1) == '=') {
op++;
*op = '\0';
iaction = LTEFUNCTION;
}
} else if ((op = strchr(mvalue1, '='))) {
iaction = GTFUNCTION;
*op = '\0';
if (*(op+1) == '=') {
op++;
*op = '\0';
iaction = EQFUNCTION;
} else
op = NULL;
}
if (op)
mvalue2 = op + 1;
if (!mvar || !mvalue1 || !mvalue2) {
ast_log(LOG_WARNING, "Supply all the parameters - just this once, please\n");
LOCAL_USER_REMOVE(u);
return -1;
}
if (!strcmp(mvar,"")) {
ast_log(LOG_WARNING, "No return variable set.\n");
LOCAL_USER_REMOVE(u);
return -1;
}
if (sscanf(mvalue1, "%f", &fnum1) != 1) {
ast_log(LOG_WARNING, "'%s' is not a valid number\n", mvalue1);
LOCAL_USER_REMOVE(u);
return -1;
}
if (sscanf(mvalue2, "%f", &fnum2) != 1) {
ast_log(LOG_WARNING, "'%s' is not a valid number\n", mvalue2);
LOCAL_USER_REMOVE(u);
return -1;
}
switch (iaction) {
case ADDFUNCTION :
ftmp = fnum1 + fnum2;
break;
case DIVIDEFUNCTION :
if (fnum2 <=0)
ftmp = 0; /* can't do a divide by 0 */
else
ftmp = (fnum1 / fnum2);
break;
case MULTIPLYFUNCTION :
ftmp = (fnum1 * fnum2);
break;
case SUBTRACTFUNCTION :
ftmp = (fnum1 - fnum2);
break;
case MODULUSFUNCTION : {
int inum1 = fnum1;
int inum2 = fnum2;
ftmp = (inum1 % inum2);
break;
}
case GTFUNCTION :
if (fnum1 > fnum2)
strcpy(user_result, "TRUE");
else
strcpy(user_result, "FALSE");
break;
case LTFUNCTION :
if (fnum1 < fnum2)
strcpy(user_result, "TRUE");
else
strcpy(user_result, "FALSE");
break;
case GTEFUNCTION :
if (fnum1 >= fnum2)
strcpy(user_result, "TRUE");
else
strcpy(user_result, "FALSE");
break;
case LTEFUNCTION :
if (fnum1 <= fnum2)
strcpy(user_result, "TRUE");
else
strcpy(user_result, "FALSE");
break;
case EQFUNCTION :
if (fnum1 == fnum2)
strcpy(user_result, "TRUE");
else
strcpy(user_result, "FALSE");
break;
default :
ast_log(LOG_WARNING, "Something happened that neither of us should be proud of %d\n", iaction);
LOCAL_USER_REMOVE(u);
return -1;
}
if (iaction < GTFUNCTION || iaction > EQFUNCTION)
snprintf(user_result,sizeof(user_result),"%f",ftmp);
pbx_builtin_setvar_helper(chan, mvar, user_result);
LOCAL_USER_REMOVE(u);
return 0;
}
int unload_module(void)
{
int res;
res = ast_unregister_application(app_math);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
int load_module(void)
{
return ast_register_application(app_math, math_exec, math_synopsis, math_descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}
/* Fading everything to black and blue... */

205
apps/app_md5.c Normal file
View File

@@ -0,0 +1,205 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2005, Olle E. Johansson, Edvina.net
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief MD5 checksum application
*
* \todo Remove this deprecated application in 1.3dev
* \ingroup applications
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/utils.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/app.h"
static char *tdesc_md5 = "MD5 checksum applications";
static char *app_md5 = "MD5";
static char *desc_md5 = "Calculate MD5 checksum";
static char *synopsis_md5 =
" MD5(<var>=<string>): Calculates a MD5 checksum on <string>.\n"
"Returns hash value in a channel variable. \n";
static char *app_md5check = "MD5Check";
static char *desc_md5check = "Check MD5 checksum";
static char *synopsis_md5check =
" MD5Check(<md5hash>|<string>[|options]): Calculates a MD5 checksum on <string>\n"
"and compares it with the hash. Returns 0 if <md5hash> is correct for <string>.\n"
"The option string may contain zero or more of the following characters:\n"
" 'j' -- jump to priority n+101 if the hash and string do not match \n"
"This application sets the following channel variable upon completion:\n"
" CHECKMD5STATUS The status of the MD5 check, one of the following\n"
" MATCH | NOMATCH\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
/*--- md5_exec: Calculate MD5 checksum (hash) on given string and
return it in channel variable ---*/
static int md5_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
char *varname= NULL; /* Variable to set */
char *string = NULL; /* String to calculate on */
char retvar[50]; /* Return value */
static int dep_warning = 0;
if (!dep_warning) {
ast_log(LOG_WARNING, "This application has been deprecated, please use the MD5 function instead.\n");
dep_warning = 1;
}
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Syntax: md5(<varname>=<string>) - missing argument!\n");
return -1;
}
LOCAL_USER_ADD(u);
memset(retvar,0, sizeof(retvar));
string = ast_strdupa(data);
varname = strsep(&string,"=");
if (ast_strlen_zero(varname)) {
ast_log(LOG_WARNING, "Syntax: md5(<varname>=<string>) - missing argument!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
ast_md5_hash(retvar, string);
pbx_builtin_setvar_helper(chan, varname, retvar);
LOCAL_USER_REMOVE(u);
return res;
}
/*--- md5check_exec: Calculate MD5 checksum and compare it with
existing checksum. ---*/
static int md5check_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
char *string = NULL; /* String to calculate on */
char newhash[50]; /* Return value */
static int dep_warning = 0;
int priority_jump = 0;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(md5hash);
AST_APP_ARG(string);
AST_APP_ARG(options);
);
if (!dep_warning) {
ast_log(LOG_WARNING, "This application has been deprecated, please use the CHECK_MD5 function instead.\n");
dep_warning = 1;
}
LOCAL_USER_ADD(u);
if (!(string = ast_strdupa(data))) {
ast_log(LOG_WARNING, "Memory Error!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
AST_STANDARD_APP_ARGS(args, string);
if (args.options) {
if (strchr(args.options, 'j'))
priority_jump = 1;
}
if (ast_strlen_zero(args.md5hash) || ast_strlen_zero(args.string)) {
ast_log(LOG_WARNING, "Syntax: MD5Check(<md5hash>|<string>[|options]) - missing argument!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
memset(newhash,0, sizeof(newhash));
ast_md5_hash(newhash, args.string);
if (!strcmp(newhash, args.md5hash)) { /* Verification ok */
if (option_debug > 2)
ast_log(LOG_DEBUG, "MD5 verified ok: %s -- %s\n", args.md5hash, args.string);
pbx_builtin_setvar_helper(chan, "CHECKMD5STATUS", "MATCH");
LOCAL_USER_REMOVE(u);
return 0;
}
if (option_debug > 2)
ast_log(LOG_DEBUG, "ERROR: MD5 not verified: %s -- %s\n", args.md5hash, args.string);
pbx_builtin_setvar_helper(chan, "CHECKMD5STATUS", "NOMATCH");
if (priority_jump || option_priority_jumping) {
if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101))
if (option_debug > 2)
ast_log(LOG_DEBUG, "Can't jump to exten+101 (e%s,p%d), sorry\n", chan->exten,chan->priority+101);
}
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
int res;
res = ast_unregister_application(app_md5);
res |= ast_unregister_application(app_md5check);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
int load_module(void)
{
int res;
res = ast_register_application(app_md5check, md5check_exec, desc_md5check, synopsis_md5check);
res |= ast_register_application(app_md5, md5_exec, desc_md5, synopsis_md5);
return res;
}
char *description(void)
{
return tdesc_md5;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

File diff suppressed because it is too large Load Diff

View File

@@ -19,51 +19,49 @@
/*! \file
*
* \brief Digital Milliwatt Test
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
/*** MODULEINFO
<depend>res_indications</depend>
***/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/utils.h"
static char *tdesc = "Digital Milliwatt (mu-law) Test Application";
static char *app = "Milliwatt";
static char *synopsis = "Generate a Constant 1004Hz tone at 0dbm (mu-law)";
static char *synopsis = "Generate a Constant 1000Hz tone at 0dbm (mu-law)";
static char *descrip =
" Milliwatt([options]): Generate a Constant 1004Hz tone at 0dbm.\n"
"Previous versions of this application generated the tone at 1000Hz. If for\n"
"some reason you would prefer that behavior, supply the 'o' option to get the\n"
"old behavior.\n"
"";
"Milliwatt(): Generate a Constant 1000Hz tone at 0dbm (mu-law)\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static char digital_milliwatt[] = {0x1e,0x0b,0x0b,0x1e,0x9e,0x8b,0x8b,0x9e} ;
static void *milliwatt_alloc(struct ast_channel *chan, void *params)
{
return ast_calloc(1, sizeof(int));
int *indexp;
indexp = malloc(sizeof(int));
if (indexp == NULL) return(NULL);
*indexp = 0;
return(indexp);
}
static void milliwatt_release(struct ast_channel *chan, void *data)
@@ -74,121 +72,99 @@ static void milliwatt_release(struct ast_channel *chan, void *data)
static int milliwatt_generate(struct ast_channel *chan, void *data, int len, int samples)
{
struct ast_frame wf;
unsigned char buf[AST_FRIENDLY_OFFSET + 640];
const int maxsamples = sizeof (buf) / sizeof (buf[0]);
int i, *indexp = (int *) data;
struct ast_frame wf = {
.frametype = AST_FRAME_VOICE,
.subclass = AST_FORMAT_ULAW,
.offset = AST_FRIENDLY_OFFSET,
.data = buf + AST_FRIENDLY_OFFSET,
.src = __FUNCTION__,
};
int i,*indexp = (int *) data;
/* Instead of len, use samples, because channel.c generator_force
* generate(chan, tmp, 0, 160) ignores len. In any case, len is
* a multiple of samples, given by number of samples times bytes per
* sample. In the case of ulaw, len = samples. for signed linear
* len = 2 * samples */
if (samples > maxsamples) {
ast_log(LOG_WARNING, "Only doing %d samples (%d requested)\n", maxsamples, samples);
samples = maxsamples;
if (len + AST_FRIENDLY_OFFSET > sizeof(buf))
{
ast_log(LOG_WARNING,"Only doing %d bytes (%d bytes requested)\n",(int)(sizeof(buf) - AST_FRIENDLY_OFFSET),len);
len = sizeof(buf) - AST_FRIENDLY_OFFSET;
}
len = samples * sizeof (buf[0]);
wf.frametype = AST_FRAME_VOICE;
wf.subclass = AST_FORMAT_ULAW;
wf.offset = AST_FRIENDLY_OFFSET;
wf.mallocd = 0;
wf.data = buf + AST_FRIENDLY_OFFSET;
wf.datalen = len;
wf.samples = samples;
wf.samples = wf.datalen;
wf.src = "app_milliwatt";
wf.delivery.tv_sec = 0;
wf.delivery.tv_usec = 0;
wf.prev = wf.next = NULL;
/* create a buffer containing the digital milliwatt pattern */
for (i = 0; i < len; i++) {
for(i = 0; i < len; i++)
{
buf[AST_FRIENDLY_OFFSET + i] = digital_milliwatt[(*indexp)++];
*indexp &= 7;
}
if (ast_write(chan,&wf) < 0) {
if (ast_write(chan,&wf) < 0)
{
ast_log(LOG_WARNING,"Failed to write frame to '%s': %s\n",chan->name,strerror(errno));
return -1;
}
return 0;
}
static struct ast_generator milliwattgen = {
static struct ast_generator milliwattgen =
{
alloc: milliwatt_alloc,
release: milliwatt_release,
generate: milliwatt_generate,
};
static int old_milliwatt_exec(struct ast_channel *chan)
{
ast_set_write_format(chan, AST_FORMAT_ULAW);
ast_set_read_format(chan, AST_FORMAT_ULAW);
if (chan->_state != AST_STATE_UP) {
ast_answer(chan);
}
if (ast_activate_generator(chan,&milliwattgen,"milliwatt") < 0) {
ast_log(LOG_WARNING,"Failed to activate generator on '%s'\n",chan->name);
return -1;
}
while (!ast_safe_sleep(chan, 10000))
;
ast_deactivate_generator(chan);
return -1;
}
} ;
static int milliwatt_exec(struct ast_channel *chan, void *data)
{
const char *options = data;
struct ast_app *playtones_app;
struct ast_module_user *u;
int res = -1;
u = ast_module_user_add(chan);
if (!ast_strlen_zero(options) && strchr(options, 'o')) {
res = old_milliwatt_exec(chan);
goto exit_app;
struct localuser *u;
LOCAL_USER_ADD(u);
ast_set_write_format(chan, AST_FORMAT_ULAW);
ast_set_read_format(chan, AST_FORMAT_ULAW);
if (chan->_state != AST_STATE_UP)
{
ast_answer(chan);
}
if (!(playtones_app = pbx_findapp("Playtones"))) {
ast_log(LOG_ERROR, "The Playtones application is required to run Milliwatt()\n");
goto exit_app;
if (ast_activate_generator(chan,&milliwattgen,"milliwatt") < 0)
{
ast_log(LOG_WARNING,"Failed to activate generator on '%s'\n",chan->name);
LOCAL_USER_REMOVE(u);
return -1;
}
res = pbx_exec(chan, playtones_app, "1004/1000");
while (!res) {
res = ast_safe_sleep(chan, 10000);
}
res = 0;
exit_app:
ast_module_user_remove(u);
return res;
while(!ast_safe_sleep(chan, 10000));
ast_deactivate_generator(chan);
LOCAL_USER_REMOVE(u);
return -1;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, milliwatt_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Digital Milliwatt (mu-law) Test Application");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -2,7 +2,7 @@
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2005, Anthony Minessale II
* Copyright (C) 2005 - 2006, Digium, Inc.
* Copyright (C) 2005, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
* Kevin P. Fleming <kpfleming@digium.com>
@@ -22,30 +22,23 @@
*/
/*! \file
*
* \brief MixMonitor() - Record a call and mix the audio during the recording
* \ingroup applications
*
* \author Mark Spencer <markster@digium.com>
* \author Kevin P. Fleming <kpfleming@digium.com>
*
* \note Based on app_muxmon.c provided by
* Anthony Minessale II <anthmct@yahoo.com>
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/audiohook.h"
#include "asterisk/chanspy.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/lock.h"
@@ -53,10 +46,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/options.h"
#include "asterisk/app.h"
#include "asterisk/linkedlists.h"
#include "asterisk/utils.h"
#define get_volfactor(x) x ? ((x > 0) ? (1 << x) : ((1 << abs(x)) * -1)) : 0
static const char *tdesc = "Mixed Audio Monitoring Application";
static const char *app = "MixMonitor";
static const char *synopsis = "Record a call and mix the audio during the recording";
static const char *desc = ""
@@ -68,37 +61,30 @@ static const char *desc = ""
"Valid options:\n"
" a - Append to the file instead of overwriting it.\n"
" b - Only save audio to the file while the channel is bridged.\n"
" Note: Does not include conferences or sounds played to each bridged\n"
" party.\n"
" Note: does not include conferences.\n"
" v(<x>) - Adjust the heard volume by a factor of <x> (range -4 to 4)\n"
" V(<x>) - Adjust the spoken volume by a factor of <x> (range -4 to 4)\n"
" W(<x>) - Adjust the both heard and spoken volumes by a factor of <x>\n"
" (range -4 to 4)\n\n"
"<command> will be executed when the recording is over\n"
"Any strings matching ^{X} will be unescaped to ${X}.\n"
"All variables will be evaluated at the time MixMonitor is called.\n"
"Any strings matching ^{X} will be unescaped to ${X} and \n"
"all variables will be evaluated at that time.\n"
"The variable MIXMONITOR_FILENAME will contain the filename used to record.\n"
"";
static const char *stop_app = "StopMixMonitor";
static const char *stop_synopsis = "Stop recording a call through MixMonitor";
static const char *stop_desc = ""
" StopMixMonitor()\n\n"
"Stops the audio recording that was started with a call to MixMonitor()\n"
"on the current channel.\n"
"";
STANDARD_LOCAL_USER;
struct module_symbols *me;
LOCAL_USER_DECL;
static const char *mixmonitor_spy_type = "MixMonitor";
struct mixmonitor {
struct ast_audiohook audiohook;
struct ast_channel *chan;
char *filename;
char *post_process;
char *name;
unsigned int flags;
struct mixmonitor_ds *mixmonitor_ds;
int readvol;
int writevol;
};
enum {
@@ -124,51 +110,22 @@ AST_APP_OPTIONS(mixmonitor_opts, {
AST_APP_OPTION_ARG('W', MUXFLAG_VOLUME, OPT_ARG_VOLUME),
});
/* This structure is used as a means of making sure that our pointer to
* the channel we are monitoring remains valid. This is very similar to
* what is used in app_chanspy.c.
*/
struct mixmonitor_ds {
struct ast_channel *chan;
/* These condition variables are used to be sure that the channel
* hangup code completes before the mixmonitor thread attempts to
* free this structure. The combination of a bookean flag and a
* ast_cond_t ensure that no matter what order the threads run in,
* we are guaranteed to never have the waiting thread block forever
* in the case that the signaling thread runs first.
*/
unsigned int destruction_ok;
ast_cond_t destruction_condition;
ast_mutex_t lock;
};
static void mixmonitor_ds_destroy(void *data)
static void stopmon(struct ast_channel *chan, struct ast_channel_spy *spy)
{
struct mixmonitor_ds *mixmonitor_ds = data;
/* If our status has changed to DONE, then the channel we're spying on is gone....
DON'T TOUCH IT!!! RUN AWAY!!! */
if (spy->status == CHANSPY_DONE)
return;
ast_mutex_lock(&mixmonitor_ds->lock);
mixmonitor_ds->chan = NULL;
mixmonitor_ds->destruction_ok = 1;
ast_cond_signal(&mixmonitor_ds->destruction_condition);
ast_mutex_unlock(&mixmonitor_ds->lock);
if (!chan)
return;
ast_mutex_lock(&chan->lock);
ast_channel_spy_remove(chan, spy);
ast_mutex_unlock(&chan->lock);
}
static void mixmonitor_ds_chan_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
{
struct mixmonitor_ds *mixmonitor_ds = data;
ast_mutex_lock(&mixmonitor_ds->lock);
mixmonitor_ds->chan = new_chan;
ast_mutex_unlock(&mixmonitor_ds->lock);
}
static struct ast_datastore_info mixmonitor_ds_info = {
.type = "mixmonitor",
.destroy = mixmonitor_ds_destroy,
.chan_fixup = mixmonitor_ds_chan_fixup,
};
static int startmon(struct ast_channel *chan, struct ast_audiohook *audiohook)
static int startmon(struct ast_channel *chan, struct ast_channel_spy *spy)
{
struct ast_channel *peer;
int res;
@@ -176,8 +133,10 @@ static int startmon(struct ast_channel *chan, struct ast_audiohook *audiohook)
if (!chan)
return -1;
res = ast_audiohook_attach(chan, audiohook);
ast_mutex_lock(&chan->lock);
res = ast_channel_spy_add(chan, spy);
ast_mutex_unlock(&chan->lock);
if (!res && ast_test_flag(chan, AST_FLAG_NBRIDGE) && (peer = ast_bridged_channel(chan)))
ast_softhangup(peer, AST_SOFTHANGUP_UNBRIDGE);
@@ -189,194 +148,169 @@ static int startmon(struct ast_channel *chan, struct ast_audiohook *audiohook)
static void *mixmonitor_thread(void *obj)
{
struct mixmonitor *mixmonitor = obj;
struct ast_channel_spy spy;
struct ast_filestream *fs = NULL;
char *ext, *name;
unsigned int oflags;
char *ext;
int errflag = 0;
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "Begin MixMonitor Recording %s\n", mixmonitor->name);
struct ast_frame *f;
char post_process[1024] = "";
ast_audiohook_lock(&mixmonitor->audiohook);
STANDARD_INCREMENT_USECOUNT;
while (mixmonitor->audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING) {
struct ast_frame *fr = NULL;
name = ast_strdupa(mixmonitor->chan->name);
oflags = O_CREAT|O_WRONLY;
oflags |= ast_test_flag(mixmonitor, MUXFLAG_APPEND) ? O_APPEND : O_TRUNC;
ast_audiohook_trigger_wait(&mixmonitor->audiohook);
if (mixmonitor->audiohook.status != AST_AUDIOHOOK_STATUS_RUNNING)
break;
if (!(fr = ast_audiohook_read_frame(&mixmonitor->audiohook, SAMPLES_PER_FRAME, AST_AUDIOHOOK_DIRECTION_BOTH, AST_FORMAT_SLINEAR)))
continue;
ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock);
if (!ast_test_flag(mixmonitor, MUXFLAG_BRIDGED) || (mixmonitor->mixmonitor_ds->chan && ast_bridged_channel(mixmonitor->mixmonitor_ds->chan))) {
ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock);
/* Initialize the file if not already done so */
if (!fs && !errflag) {
oflags = O_CREAT | O_WRONLY;
oflags |= ast_test_flag(mixmonitor, MUXFLAG_APPEND) ? O_APPEND : O_TRUNC;
if ((ext = strrchr(mixmonitor->filename, '.')))
*(ext++) = '\0';
else
ext = "raw";
if (!(fs = ast_writefile(mixmonitor->filename, ext, NULL, oflags, 0, 0644))) {
ast_log(LOG_ERROR, "Cannot open %s.%s\n", mixmonitor->filename, ext);
errflag = 1;
}
}
/* Write out the frame */
if (fs)
ast_writestream(fs, fr);
} else {
ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock);
}
/* All done! free it. */
ast_frame_free(fr, 0);
if ((ext = strrchr(mixmonitor->filename, '.'))) {
*(ext++) = '\0';
} else {
ext = "raw";
}
ast_audiohook_detach(&mixmonitor->audiohook);
ast_audiohook_unlock(&mixmonitor->audiohook);
ast_audiohook_destroy(&mixmonitor->audiohook);
fs = ast_writefile(mixmonitor->filename, ext, NULL, oflags, 0, 0644);
if (!fs) {
ast_log(LOG_ERROR, "Cannot open %s.%s\n", mixmonitor->filename, ext);
goto out;
}
if (ast_test_flag(mixmonitor, MUXFLAG_APPEND))
ast_seekstream(fs, 0, SEEK_END);
memset(&spy, 0, sizeof(spy));
ast_set_flag(&spy, CHANSPY_FORMAT_AUDIO);
ast_set_flag(&spy, CHANSPY_MIXAUDIO);
spy.type = mixmonitor_spy_type;
spy.status = CHANSPY_RUNNING;
spy.read_queue.format = AST_FORMAT_SLINEAR;
spy.write_queue.format = AST_FORMAT_SLINEAR;
if (mixmonitor->readvol) {
ast_set_flag(&spy, CHANSPY_READ_VOLADJUST);
spy.read_vol_adjustment = mixmonitor->readvol;
}
if (mixmonitor->writevol) {
ast_set_flag(&spy, CHANSPY_WRITE_VOLADJUST);
spy.write_vol_adjustment = mixmonitor->writevol;
}
ast_mutex_init(&spy.lock);
if (startmon(mixmonitor->chan, &spy)) {
ast_log(LOG_WARNING, "Unable to add '%s' spy to channel '%s'\n",
spy.type, mixmonitor->chan->name);
goto out2;
}
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "End MixMonitor Recording %s\n", mixmonitor->name);
ast_verbose(VERBOSE_PREFIX_2 "Begin MixMonitor Recording %s\n", name);
if (mixmonitor->post_process) {
char *p;
for (p = mixmonitor->post_process; *p ; p++) {
if (*p == '^' && *(p+1) == '{') {
*p = '$';
}
}
pbx_substitute_variables_helper(mixmonitor->chan, mixmonitor->post_process, post_process, sizeof(post_process) - 1);
}
while (1) {
struct ast_frame *next;
int write;
ast_mutex_lock(&spy.lock);
ast_channel_spy_trigger_wait(&spy);
if (ast_check_hangup(mixmonitor->chan) || spy.status != CHANSPY_RUNNING) {
ast_mutex_unlock(&spy.lock);
break;
}
while (1) {
if (!(f = ast_channel_spy_read_frame(&spy, SAMPLES_PER_FRAME)))
break;
write = (!ast_test_flag(mixmonitor, MUXFLAG_BRIDGED) ||
ast_bridged_channel(mixmonitor->chan));
/* it is possible for ast_channel_spy_read_frame() to return a chain
of frames if a queue flush was necessary, so process them
*/
for (; f; f = next) {
next = f->next;
if (write)
ast_writestream(fs, f);
ast_frfree(f);
}
}
ast_mutex_unlock(&spy.lock);
}
stopmon(mixmonitor->chan, &spy);
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "End MixMonitor Recording %s\n", name);
if (!ast_strlen_zero(post_process)) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_2 "Executing [%s]\n", post_process);
ast_safe_system(post_process);
}
out2:
ast_mutex_destroy(&spy.lock);
if (fs)
ast_closestream(fs);
if (mixmonitor->post_process) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_2 "Executing [%s]\n", mixmonitor->post_process);
ast_safe_system(mixmonitor->post_process);
}
ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock);
if (!mixmonitor->mixmonitor_ds->destruction_ok) {
ast_cond_wait(&mixmonitor->mixmonitor_ds->destruction_condition, &mixmonitor->mixmonitor_ds->lock);
}
ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock);
ast_mutex_destroy(&mixmonitor->mixmonitor_ds->lock);
ast_cond_destroy(&mixmonitor->mixmonitor_ds->destruction_condition);
ast_free(mixmonitor->mixmonitor_ds);
out:
free(mixmonitor);
STANDARD_DECREMENT_USECOUNT;
return NULL;
}
static int setup_mixmonitor_ds(struct mixmonitor *mixmonitor, struct ast_channel *chan)
{
struct ast_datastore *datastore = NULL;
struct mixmonitor_ds *mixmonitor_ds;
if (!(mixmonitor_ds = ast_calloc(1, sizeof(*mixmonitor_ds)))) {
return -1;
}
ast_mutex_init(&mixmonitor_ds->lock);
ast_cond_init(&mixmonitor_ds->destruction_condition, NULL);
if (!(datastore = ast_channel_datastore_alloc(&mixmonitor_ds_info, NULL))) {
ast_free(mixmonitor_ds);
return -1;
}
/* No need to lock mixmonitor_ds since this is still operating in the channel's thread */
mixmonitor_ds->chan = chan;
datastore->data = mixmonitor_ds;
ast_channel_lock(chan);
ast_channel_datastore_add(chan, datastore);
ast_channel_unlock(chan);
mixmonitor->mixmonitor_ds = mixmonitor_ds;
return 0;
}
static void launch_monitor_thread(struct ast_channel *chan, const char *filename, unsigned int flags,
int readvol, int writevol, const char *post_process)
{
pthread_attr_t attr;
pthread_t thread;
struct mixmonitor *mixmonitor;
char postprocess2[1024] = "";
size_t len;
int len;
len = sizeof(*mixmonitor) + strlen(chan->name) + strlen(filename) + 2;
len = sizeof(*mixmonitor) + strlen(filename) + 1;
if (!ast_strlen_zero(post_process))
len += strlen(post_process) + 1;
/* If a post process system command is given attach it to the structure */
if (!ast_strlen_zero(post_process)) {
char *p1, *p2;
p1 = ast_strdupa(post_process);
for (p2 = p1; *p2 ; p2++) {
if (*p2 == '^' && *(p2+1) == '{') {
*p2 = '$';
}
}
pbx_substitute_variables_helper(chan, p1, postprocess2, sizeof(postprocess2) - 1);
if (!ast_strlen_zero(postprocess2))
len += strlen(postprocess2) + 1;
}
/* Pre-allocate mixmonitor structure and spy */
if (!(mixmonitor = calloc(1, len))) {
ast_log(LOG_ERROR, "Memory Error!\n");
return;
}
/* Copy over flags and channel name */
mixmonitor->flags = flags;
if (setup_mixmonitor_ds(mixmonitor, chan)) {
return;
}
mixmonitor->name = (char *) mixmonitor + sizeof(*mixmonitor);
strcpy(mixmonitor->name, chan->name);
if (!ast_strlen_zero(postprocess2)) {
mixmonitor->post_process = mixmonitor->name + strlen(mixmonitor->name) + strlen(filename) + 2;
strcpy(mixmonitor->post_process, postprocess2);
}
mixmonitor->filename = (char *) mixmonitor + sizeof(*mixmonitor) + strlen(chan->name) + 1;
mixmonitor->chan = chan;
mixmonitor->filename = (char *) mixmonitor + sizeof(*mixmonitor);
strcpy(mixmonitor->filename, filename);
/* Setup the actual spy before creating our thread */
if (ast_audiohook_init(&mixmonitor->audiohook, AST_AUDIOHOOK_TYPE_SPY, mixmonitor_spy_type)) {
free(mixmonitor);
return;
}
ast_set_flag(&mixmonitor->audiohook, AST_AUDIOHOOK_TRIGGER_SYNC);
if (readvol)
mixmonitor->audiohook.options.read_volume = readvol;
if (writevol)
mixmonitor->audiohook.options.write_volume = writevol;
if (startmon(chan, &mixmonitor->audiohook)) {
ast_log(LOG_WARNING, "Unable to add '%s' spy to channel '%s'\n",
mixmonitor_spy_type, chan->name);
/* Since we couldn't add ourselves - bail out! */
ast_audiohook_destroy(&mixmonitor->audiohook);
free(mixmonitor);
return;
if (!ast_strlen_zero(post_process)) {
mixmonitor->post_process = mixmonitor->filename + strlen(filename) + 1;
strcpy(mixmonitor->post_process, post_process);
}
mixmonitor->readvol = readvol;
mixmonitor->writevol = writevol;
mixmonitor->flags = flags;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
ast_pthread_create_background(&thread, &attr, mixmonitor_thread, mixmonitor);
ast_pthread_create(&thread, &attr, mixmonitor_thread, mixmonitor);
pthread_attr_destroy(&attr);
}
static int mixmonitor_exec(struct ast_channel *chan, void *data)
{
int x, readvol = 0, writevol = 0;
struct ast_module_user *u;
struct localuser *u;
struct ast_flags flags = {0};
char *parse;
AST_DECLARE_APP_ARGS(args,
@@ -390,15 +324,19 @@ static int mixmonitor_exec(struct ast_channel *chan, void *data)
return -1;
}
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
parse = ast_strdupa(data);
if (!(parse = ast_strdupa(data))) {
ast_log(LOG_WARNING, "Memory Error!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
AST_STANDARD_APP_ARGS(args, parse);
if (ast_strlen_zero(args.filename)) {
ast_log(LOG_WARNING, "MixMonitor requires an argument (filename)\n");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
@@ -450,20 +388,7 @@ static int mixmonitor_exec(struct ast_channel *chan, void *data)
pbx_builtin_setvar_helper(chan, "MIXMONITOR_FILENAME", args.filename);
launch_monitor_thread(chan, args.filename, flags.flags, readvol, writevol, args.post_process);
ast_module_user_remove(u);
return 0;
}
static int stop_mixmonitor_exec(struct ast_channel *chan, void *data)
{
struct ast_module_user *u;
u = ast_module_user_add(chan);
ast_audiohook_detach_source(chan, mixmonitor_spy_type);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return 0;
}
@@ -483,49 +408,59 @@ static int mixmonitor_cli(int fd, int argc, char **argv)
if (!strcasecmp(argv[1], "start"))
mixmonitor_exec(chan, argv[3]);
else if (!strcasecmp(argv[1], "stop"))
ast_audiohook_detach_source(chan, mixmonitor_spy_type);
ast_channel_spy_stop_by_type(chan, mixmonitor_spy_type);
ast_channel_unlock(chan);
ast_mutex_unlock(&chan->lock);
return RESULT_SUCCESS;
}
static char *complete_mixmonitor_cli(const char *line, const char *word, int pos, int state)
{
return ast_complete_channels(line, word, pos, state, 2);
}
static struct ast_cli_entry cli_mixmonitor[] = {
{ { "mixmonitor", NULL, NULL },
mixmonitor_cli, "Execute a MixMonitor command.",
"mixmonitor <start|stop> <chan_name> [args]\n\n"
"The optional arguments are passed to the\n"
"MixMonitor application when the 'start' command is used.\n",
complete_mixmonitor_cli },
static struct ast_cli_entry cli_mixmonitor = {
{ "mixmonitor", NULL, NULL },
mixmonitor_cli,
"Execute a MixMonitor command",
"mixmonitor <start|stop> <chan_name> [<args>]\n"
};
static int unload_module(void)
int unload_module(void)
{
int res;
ast_cli_unregister_multiple(cli_mixmonitor, sizeof(cli_mixmonitor) / sizeof(struct ast_cli_entry));
res = ast_unregister_application(stop_app);
res = ast_cli_unregister(&cli_mixmonitor);
res |= ast_unregister_application(app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
int res;
ast_cli_register_multiple(cli_mixmonitor, sizeof(cli_mixmonitor) / sizeof(struct ast_cli_entry));
res = ast_register_application(app, mixmonitor_exec, synopsis, desc);
res |= ast_register_application(stop_app, stop_mixmonitor_exec, stop_synopsis, stop_desc);
res = ast_cli_register(&cli_mixmonitor);
res |= ast_register_application(app, mixmonitor_exec, synopsis, desc);
return res;
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Mixed Audio Monitoring Application");
char *description(void)
{
return (char *) tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,179 +0,0 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (c) 2006, Tilghman Lesher. All rights reserved.
*
* Tilghman Lesher <app_morsecode__v001@the-tilghman.com>
*
* This code is released by the author with no restrictions on usage.
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
*/
/*! \file
*
* \brief Morsecode application
*
* \author Tilghman Lesher <app_morsecode__v001@the-tilghman.com>
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/indications.h"
static char *app_morsecode = "Morsecode";
static char *morsecode_synopsis = "Plays morse code";
static char *morsecode_descrip =
"Usage: Morsecode(<string>)\n"
"Plays the Morse code equivalent of the passed string. If the variable\n"
"MORSEDITLEN is set, it will use that value for the length (in ms) of the dit\n"
"(defaults to 80). Additionally, if MORSETONE is set, it will use that tone\n"
"(in Hz). The tone default is 800.\n";
static char *morsecode[] = {
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /* 0-15 */
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /* 16-31 */
" ", /* 32 - <space> */
".-.-.-", /* 33 - ! */
".-..-.", /* 34 - " */
"", /* 35 - # */
"", /* 36 - $ */
"", /* 37 - % */
"", /* 38 - & */
".----.", /* 39 - ' */
"-.--.-", /* 40 - ( */
"-.--.-", /* 41 - ) */
"", /* 42 - * */
"", /* 43 - + */
"--..--", /* 44 - , */
"-....-", /* 45 - - */
".-.-.-", /* 46 - . */
"-..-.", /* 47 - / */
"-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----.", /* 48-57 - 0-9 */
"---...", /* 58 - : */
"-.-.-.", /* 59 - ; */
"", /* 60 - < */
"-...-", /* 61 - = */
"", /* 62 - > */
"..--..", /* 63 - ? */
".--.-.", /* 64 - @ */
".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--",
"-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..",
"-.--.-", /* 91 - [ (really '(') */
"-..-.", /* 92 - \ (really '/') */
"-.--.-", /* 93 - ] (really ')') */
"", /* 94 - ^ */
"..--.-", /* 95 - _ */
".----.", /* 96 - ` */
".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--",
"-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..",
"-.--.-", /* 123 - { (really '(') */
"", /* 124 - | */
"-.--.-", /* 125 - } (really ')') */
"-..-.", /* 126 - ~ (really bar) */
". . .", /* 127 - <del> (error) */
};
static void playtone(struct ast_channel *chan, int tone, int len)
{
char dtmf[20];
snprintf(dtmf, sizeof(dtmf), "%d/%d", tone, len);
ast_playtones_start(chan, 0, dtmf, 0);
ast_safe_sleep(chan, len);
ast_playtones_stop(chan);
}
static int morsecode_exec(struct ast_channel *chan, void *data)
{
int res=0, ditlen, tone;
char *digit;
const char *ditlenc, *tonec;
struct ast_module_user *u;
u = ast_module_user_add(chan);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Syntax: Morsecode(<string>) - no argument found\n");
ast_module_user_remove(u);
return 0;
}
/* Use variable MORESEDITLEN, if set (else 80) */
ditlenc = pbx_builtin_getvar_helper(chan, "MORSEDITLEN");
if (ast_strlen_zero(ditlenc) || (sscanf(ditlenc, "%d", &ditlen) != 1)) {
ditlen = 80;
}
/* Use variable MORSETONE, if set (else 800) */
tonec = pbx_builtin_getvar_helper(chan, "MORSETONE");
if (ast_strlen_zero(tonec) || (sscanf(tonec, "%d", &tone) != 1)) {
tone = 800;
}
for (digit = data; *digit; digit++) {
int digit2 = *digit;
char *dahdit;
if (digit2 < 0) {
continue;
}
for (dahdit = morsecode[digit2]; *dahdit; dahdit++) {
if (*dahdit == '-') {
playtone(chan, tone, 3 * ditlen);
} else if (*dahdit == '.') {
playtone(chan, tone, 1 * ditlen);
} else {
/* Account for ditlen of silence immediately following */
playtone(chan, 0, 2 * ditlen);
}
/* Pause slightly between each dit and dah */
playtone(chan, 0, 1 * ditlen);
}
/* Pause between characters */
playtone(chan, 0, 2 * ditlen);
}
ast_module_user_remove(u);
return res;
}
static int unload_module(void)
{
int res;
res = ast_unregister_application(app_morsecode);
ast_module_user_hangup_all();
return res;
}
static int load_module(void)
{
return ast_register_application(app_morsecode, morsecode_exec, morsecode_synopsis, morsecode_descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Morse code");

View File

@@ -19,20 +19,10 @@
/*! \file
*
* \brief Silly application to play an MP3 file -- uses mpg123
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
/*** MODULEINFO
<depend>working_fork</depend>
***/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <string.h>
#include <stdio.h>
#include <signal.h>
@@ -40,9 +30,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#ifdef HAVE_CAP
#include <sys/capability.h>
#endif /* HAVE_CAP */
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
@@ -52,11 +43,12 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/options.h"
#define LOCAL_MPG_123 "/usr/local/bin/mpg123"
#define MPG_123 "/usr/bin/mpg123"
static char *tdesc = "Silly MP3 Application";
static char *app = "MP3Player";
static char *synopsis = "Play an MP3 file or stream";
@@ -66,43 +58,23 @@ static char *descrip =
"which typically would be a filename or a URL. User can exit by pressing\n"
"any key on the dialpad, or by hanging up.";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int mp3play(char *filename, int fd)
{
int res;
int x;
sigset_t fullset, oldset;
#ifdef HAVE_CAP
cap_t cap;
#endif
sigfillset(&fullset);
pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
res = fork();
if (res < 0)
ast_log(LOG_WARNING, "Fork failed\n");
if (res) {
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
if (res)
return res;
}
#ifdef HAVE_CAP
cap = cap_from_text("cap_net_admin-eip");
if (cap_set_proc(cap)) {
/* Careful with order! Logging cannot happen after we close FDs */
ast_log(LOG_WARNING, "Unable to remove capabilities.\n");
}
cap_free(cap);
#endif
if (ast_opt_high_priority)
ast_set_priority(0);
signal(SIGPIPE, SIG_DFL);
pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
dup2(fd, STDOUT_FILENO);
for (x=STDERR_FILENO + 1;x<256;x++) {
close(x);
for (x=0;x<256;x++) {
if (x != STDOUT_FILENO)
close(x);
}
/* Execute mpg123, but buffer if it's a net connection */
if (!strncasecmp(filename, "http://", 7)) {
@@ -122,7 +94,7 @@ static int mp3play(char *filename, int fd)
execlp("mpg123", "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
}
ast_log(LOG_WARNING, "Execute of mpg123 failed\n");
_exit(0);
return -1;
}
static int timed_read(int fd, void *data, int datalen, int timeout)
@@ -143,7 +115,7 @@ static int timed_read(int fd, void *data, int datalen, int timeout)
static int mp3_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct ast_module_user *u;
struct localuser *u;
int fds[2];
int ms = -1;
int pid = -1;
@@ -162,11 +134,11 @@ static int mp3_exec(struct ast_channel *chan, void *data)
return -1;
}
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
if (pipe(fds)) {
ast_log(LOG_WARNING, "Unable to create pipe\n");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
@@ -176,7 +148,7 @@ static int mp3_exec(struct ast_channel *chan, void *data)
res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
@@ -249,25 +221,40 @@ static int mp3_exec(struct ast_channel *chan, void *data)
if (!res && owriteformat)
ast_set_write_format(chan, owriteformat);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, mp3_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Silly MP3 Application");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,20 +19,10 @@
/*! \file
*
* \brief Silly application to play an NBScat file -- uses nbscat8k
*
* \author Mark Spencer <markster@digium.com>
*
*
* \ingroup applications
*/
/*** MODULEINFO
<depend>working_fork</depend>
***/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <string.h>
#include <stdio.h>
#include <signal.h>
@@ -41,9 +31,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <fcntl.h>
#include <sys/time.h>
#include <sys/socket.h>
#ifdef HAVE_CAP
#include <sys/capability.h>
#endif /* HAVE_CAP */
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
@@ -53,7 +44,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/options.h"
#define LOCAL_NBSCAT "/usr/local/bin/nbscat8k"
#define NBSCAT "/usr/bin/nbscat8k"
@@ -62,6 +52,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define AF_LOCAL AF_UNIX
#endif
static char *tdesc = "Silly NBS Stream Application";
static char *app = "NBScat";
static char *synopsis = "Play an NBS local stream";
@@ -70,43 +62,21 @@ static char *descrip =
" NBScat: Executes nbscat to listen to the local NBS stream.\n"
"User can exit by pressing any key\n.";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int NBScatplay(int fd)
{
int res;
int x;
sigset_t fullset, oldset;
#ifdef HAVE_CAP
cap_t cap;
#endif
sigfillset(&fullset);
pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
res = fork();
if (res < 0)
ast_log(LOG_WARNING, "Fork failed\n");
if (res) {
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
if (res)
return res;
}
signal(SIGPIPE, SIG_DFL);
pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
#ifdef HAVE_CAP
cap = cap_from_text("cap_net_admin-eip");
if (cap_set_proc(cap)) {
/* Careful with order! Logging cannot happen after we close FDs */
ast_log(LOG_WARNING, "Unable to remove capabilities.\n");
}
cap_free(cap);
#endif
if (ast_opt_high_priority)
ast_set_priority(0);
dup2(fd, STDOUT_FILENO);
for (x = STDERR_FILENO + 1; x < 1024; x++) {
for (x=0;x<256;x++) {
if (x != STDOUT_FILENO)
close(x);
}
@@ -114,7 +84,7 @@ static int NBScatplay(int fd)
execl(NBSCAT, "nbscat8k", "-d", (char *)NULL);
execl(LOCAL_NBSCAT, "nbscat8k", "-d", (char *)NULL);
ast_log(LOG_WARNING, "Execute of nbscat8k failed\n");
_exit(0);
return -1;
}
static int timed_read(int fd, void *data, int datalen)
@@ -135,7 +105,7 @@ static int timed_read(int fd, void *data, int datalen)
static int NBScat_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct ast_module_user *u;
struct localuser *u;
int fds[2];
int ms = -1;
int pid = -1;
@@ -148,11 +118,11 @@ static int NBScat_exec(struct ast_channel *chan, void *data)
short frdata[160];
} myf;
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds)) {
ast_log(LOG_WARNING, "Unable to create socketpair\n");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
@@ -162,7 +132,7 @@ static int NBScat_exec(struct ast_channel *chan, void *data)
res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
@@ -232,25 +202,40 @@ static int NBScat_exec(struct ast_channel *chan, void *data)
if (!res && owriteformat)
ast_set_write_format(chan, owriteformat);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, NBScat_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Silly NBS Stream Application");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

File diff suppressed because it is too large Load Diff

View File

@@ -20,26 +20,19 @@
*
* \brief page() - Paging application
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
/*** MODULEINFO
<depend>dahdi</depend>
<depend>app_meetme</depend>
***/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/options.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
@@ -48,9 +41,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/app.h"
#include "asterisk/chanvars.h"
#include "asterisk/utils.h"
#include "asterisk/dial.h"
#include "asterisk/devicestate.h"
static const char *tdesc = "Page Multiple Phones";
static const char *app_page= "Page";
@@ -63,109 +56,142 @@ static const char *page_descrip =
"caller is dumped into the conference as a speaker and the room is\n"
"destroyed when the original caller leaves. Valid options are:\n"
" d - full duplex audio\n"
" q - quiet, do not play beep to caller\n"
" r - record the page into a file (see 'r' for app_meetme)\n";
" q - quiet, do not play beep to caller\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
enum {
PAGE_DUPLEX = (1 << 0),
PAGE_QUIET = (1 << 1),
PAGE_RECORD = (1 << 2),
} page_opt_flags;
AST_APP_OPTIONS(page_opts, {
AST_APP_OPTION('d', PAGE_DUPLEX),
AST_APP_OPTION('q', PAGE_QUIET),
AST_APP_OPTION('r', PAGE_RECORD),
});
struct calloutdata {
char cidnum[64];
char cidname[64];
char tech[64];
char resource[256];
char meetmeopts[64];
struct ast_variable *variables;
};
static void *page_thread(void *data)
{
struct calloutdata *cd = data;
ast_pbx_outgoing_app(cd->tech, AST_FORMAT_SLINEAR, cd->resource, 30000,
"MeetMe", cd->meetmeopts, NULL, 0, cd->cidnum, cd->cidname, cd->variables, NULL, NULL);
free(cd);
return NULL;
}
static void launch_page(struct ast_channel *chan, const char *meetmeopts, const char *tech, const char *resource)
{
struct calloutdata *cd;
const char *varname;
struct ast_variable *lastvar = NULL;
struct ast_var_t *varptr;
pthread_t t;
pthread_attr_t attr;
cd = malloc(sizeof(struct calloutdata));
if (cd) {
memset(cd, 0, sizeof(struct calloutdata));
ast_copy_string(cd->cidnum, chan->cid.cid_num ? chan->cid.cid_num : "", sizeof(cd->cidnum));
ast_copy_string(cd->cidname, chan->cid.cid_name ? chan->cid.cid_name : "", sizeof(cd->cidname));
ast_copy_string(cd->tech, tech, sizeof(cd->tech));
ast_copy_string(cd->resource, resource, sizeof(cd->resource));
ast_copy_string(cd->meetmeopts, meetmeopts, sizeof(cd->meetmeopts));
AST_LIST_TRAVERSE(&chan->varshead, varptr, entries) {
if (!(varname = ast_var_full_name(varptr)))
continue;
if (varname[0] == '_') {
struct ast_variable *newvar = NULL;
if (varname[1] == '_') {
newvar = ast_variable_new(varname, ast_var_value(varptr));
} else {
newvar = ast_variable_new(&varname[1], ast_var_value(varptr));
}
if (newvar) {
if (lastvar)
lastvar->next = newvar;
else
cd->variables = newvar;
lastvar = newvar;
}
}
}
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (ast_pthread_create(&t, &attr, page_thread, cd)) {
ast_log(LOG_WARNING, "Unable to create paging thread: %s\n", strerror(errno));
free(cd);
}
}
}
static int page_exec(struct ast_channel *chan, void *data)
{
struct ast_module_user *u;
char *options, *tech, *resource, *tmp, *tmp2;
char meetmeopts[88], originator[AST_CHANNEL_NAME];
struct localuser *u;
char *options;
char *tech, *resource;
char meetmeopts[80];
struct ast_flags flags = { 0 };
unsigned int confid = ast_random();
unsigned int confid = rand();
struct ast_app *app;
int res = 0, pos = 0, i = 0;
struct ast_dial **dial_list;
unsigned int num_dials;
char *tmp;
int res=0;
char originator[AST_CHANNEL_NAME];
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "This application requires at least one argument (destination(s) to page)\n");
return -1;
}
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
if (!(app = pbx_findapp("MeetMe"))) {
ast_log(LOG_WARNING, "There is no MeetMe application available!\n");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
};
options = ast_strdupa(data);
ast_copy_string(originator, chan->name, sizeof(originator));
if ((tmp = strchr(originator, '-')))
*tmp = '\0';
if (!options) {
ast_log(LOG_ERROR, "Out of memory\n");
LOCAL_USER_REMOVE(u);
return -1;
}
tmp = strsep(&options, "|");
if (options)
ast_app_parse_options(page_opts, &flags, NULL, options);
snprintf(meetmeopts, sizeof(meetmeopts), "MeetMe|%ud|%s%sqxdw(5)", confid, (ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "m"),
(ast_test_flag(&flags, PAGE_RECORD) ? "r" : "") );
snprintf(meetmeopts, sizeof(meetmeopts), "%ud|%sqxdw", confid, ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "m");
/* Count number of extensions in list by number of ampersands + 1 */
num_dials = 1;
tmp2 = tmp;
while (*tmp2) {
if (*tmp2 == '&') {
num_dials++;
}
tmp2++;
}
ast_copy_string(originator, chan->name, sizeof(originator));
if ((tmp = strchr(originator, '-')))
*tmp = '\0';
if (!(dial_list = ast_calloc(num_dials, sizeof(struct ast_dial *)))) {
ast_log(LOG_ERROR, "Can't allocate %ld bytes for dial list\n", (long)(sizeof(struct ast_dial *) * num_dials));
ast_module_user_remove(u);
return -1;
}
/* Go through parsing/calling each device */
while ((tech = strsep(&tmp, "&"))) {
struct ast_dial *dial = NULL;
/* don't call the originating device */
if (!strcasecmp(tech, originator))
continue;
/* If no resource is available, continue on */
if (!(resource = strchr(tech, '/'))) {
if ((resource = strchr(tech, '/'))) {
*resource++ = '\0';
launch_page(chan, meetmeopts, tech, resource);
} else {
ast_log(LOG_WARNING, "Incomplete destination '%s' supplied.\n", tech);
continue;
}
*resource++ = '\0';
/* Create a dialing structure */
if (!(dial = ast_dial_create())) {
ast_log(LOG_WARNING, "Failed to create dialing structure.\n");
continue;
}
/* Append technology and resource */
ast_dial_append(dial, tech, resource);
/* Set ANSWER_EXEC as global option */
ast_dial_option_global_enable(dial, AST_DIAL_OPTION_ANSWER_EXEC, meetmeopts);
/* Run this dial in async mode */
ast_dial_run(dial, chan, 1);
/* Put in our dialing array */
dial_list[pos++] = dial;
}
if (!ast_test_flag(&flags, PAGE_QUIET)) {
@@ -173,48 +199,47 @@ static int page_exec(struct ast_channel *chan, void *data)
if (!res)
res = ast_waitstream(chan, "");
}
if (!res) {
snprintf(meetmeopts, sizeof(meetmeopts), "%ud|A%s%sqxd", confid, (ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "t"),
(ast_test_flag(&flags, PAGE_RECORD) ? "r" : "") );
pbx_exec(chan, app, meetmeopts);
snprintf(meetmeopts, sizeof(meetmeopts), "%ud|A%sqxd", confid, ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "t");
pbx_exec(chan, app, meetmeopts, 1);
}
/* Go through each dial attempt cancelling, joining, and destroying */
for (i = 0; i < pos; i++) {
struct ast_dial *dial = dial_list[i];
/* We have to wait for the async thread to exit as it's possible Meetme won't throw them out immediately */
ast_dial_join(dial);
/* Hangup all channels */
ast_dial_hangup(dial);
/* Destroy dialing structure */
ast_dial_destroy(dial);
}
ast_free(dial_list);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app_page);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app_page, page_exec, page_synopsis, page_descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Page Multiple Phones");
char *description(void)
{
return (char *) tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,7 +1,7 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2006, Digium, Inc.
* Copyright (C) 1999 - 2005, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
@@ -22,23 +22,20 @@
/*! \file
*
* \brief ParkAndAnnounce application for Asterisk
*
* \author Ben Miller <bgmiller@dccinc.com>
* \arg With TONS of help from Mark!
*
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
@@ -49,7 +46,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/logger.h"
#include "asterisk/say.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
static char *tdesc = "Call Parking and Announce Application";
static char *app = "ParkAndAnnounce";
@@ -57,53 +55,57 @@ static char *synopsis = "Park and Announce";
static char *descrip =
" ParkAndAnnounce(announce:template|timeout|dial|[return_context]):\n"
"Park a call into the parkinglot and announce the call to another channel.\n"
"\n"
"announce template: Colon-separated list of files to announce. The word PARKED\n"
" will be replaced by a say_digits of the extension in which\n"
" the call is parked.\n"
"timeout: Time in seconds before the call returns into the return\n"
" context.\n"
"dial: The app_dial style resource to call to make the\n"
" announcement. Console/dsp calls the console.\n"
"return_context: The goto-style label to jump the call back into after\n"
" timeout. Default <priority+1>.\n"
"\n"
"The variable ${PARKEDAT} will contain the parking extension into which the\n"
"call was placed. Use with the Local channel to allow the dialplan to make\n"
"use of this information.\n";
"Park a call into the parkinglot and announce the call over the console.\n"
"announce template: colon separated list of files to announce, the word PARKED\n"
" will be replaced by a say_digits of the ext the call is parked in\n"
"timeout: time in seconds before the call returns into the return context.\n"
"dial: The app_dial style resource to call to make the announcement. Console/dsp calls the console.\n"
"return_context: the goto style label to jump the call back into after timeout. default=prio+1\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int parkandannounce_exec(struct ast_channel *chan, void *data)
{
int res=0;
char *return_context;
int lot, timeout = 0, dres;
int l, lot, timeout = 0, dres;
char *working, *context, *exten, *priority, *dial, *dialtech, *dialstr;
char *template, *tpl_working, *tpl_current;
char *tmp[100];
char buf[13];
int looptemp = 0,i = 0, res = 0;
char *s;
int looptemp=0,i=0;
char *s,*orig_s;
struct ast_channel *dchan;
struct outgoing_helper oh;
int outstate;
struct ast_module_user *u;
struct localuser *u;
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "ParkAndAnnounce requires arguments: (announce:template|timeout|dial|[return_context])\n");
return -1;
}
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
s = ast_strdupa(data);
l=strlen(data)+2;
orig_s=malloc(l);
if(!orig_s) {
ast_log(LOG_WARNING, "Out of memory\n");
LOCAL_USER_REMOVE(u);
return -1;
}
s=orig_s;
strncpy(s,data,l);
template = strsep(&s,"|");
template=strsep(&s,"|");
if(! template) {
ast_log(LOG_WARNING, "PARK: An announce template must be defined\n");
ast_module_user_remove(u);
free(orig_s);
LOCAL_USER_REMOVE(u);
return -1;
}
@@ -111,14 +113,15 @@ static int parkandannounce_exec(struct ast_channel *chan, void *data)
timeout = atoi(strsep(&s, "|"));
timeout *= 1000;
}
dial = strsep(&s, "|");
dial=strsep(&s, "|");
if(!dial) {
ast_log(LOG_WARNING, "PARK: A dial resource must be specified i.e: Console/dsp or Zap/g1/5551212\n");
ast_module_user_remove(u);
free(orig_s);
LOCAL_USER_REMOVE(u);
return -1;
} else {
dialtech = strsep(&dial, "/");
dialstr = dial;
dialtech=strsep(&dial, "/");
dialstr=dial;
ast_verbose( VERBOSE_PREFIX_3 "Dial Tech,String: (%s,%s)\n", dialtech,dialstr);
}
@@ -146,15 +149,16 @@ static int parkandannounce_exec(struct ast_channel *chan, void *data)
}
if(atoi(priority) < 0) {
ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
ast_module_user_remove(u);
free(orig_s);
LOCAL_USER_REMOVE(u);
return -1;
}
/* At this point we have a priority and maybe an extension and a context */
chan->priority = atoi(priority);
if (exten)
ast_copy_string(chan->exten, exten, sizeof(chan->exten));
if (context)
ast_copy_string(chan->context, context, sizeof(chan->context));
if(exten && strcasecmp(exten, "BYEXTENSION"))
strncpy(chan->exten, exten, sizeof(chan->exten)-1);
if(context)
strncpy(chan->context, context, sizeof(chan->context)-1);
} else { /* increment the priority by default*/
chan->priority++;
}
@@ -169,19 +173,16 @@ static int parkandannounce_exec(struct ast_channel *chan, void *data)
/* we are using masq_park here to protect * from touching the channel once we park it. If the channel comes out of timeout
before we are done announcing and the channel is messed with, Kablooeee. So we use Masq to prevent this. */
res = ast_masq_park_call(chan, NULL, timeout, &lot);
if (res == -1) {
goto finish;
}
ast_masq_park_call(chan, NULL, timeout, &lot);
res=-1;
ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
/* Now place the call to the extention */
snprintf(buf, sizeof(buf), "%d", lot);
memset(&oh, 0, sizeof(oh));
oh.parent_channel = chan;
oh.vars = ast_variable_new("_PARKEDAT", buf);
dchan = __ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, dialstr,30000, &outstate, chan->cid.cid_num, chan->cid.cid_name, &oh);
if(dchan) {
@@ -193,12 +194,14 @@ static int parkandannounce_exec(struct ast_channel *chan, void *data)
ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", dchan->name);
ast_log(LOG_WARNING, "PARK: Channel %s was never answered for the announce.\n", dchan->name);
ast_hangup(dchan);
ast_module_user_remove(u);
free(orig_s);
LOCAL_USER_REMOVE(u);
return -1;
}
} else {
ast_log(LOG_WARNING, "PARK: Unable to allocate announce channel.\n");
ast_module_user_remove(u);
free(orig_s);
LOCAL_USER_REMOVE(u);
return -1;
}
@@ -209,15 +212,15 @@ static int parkandannounce_exec(struct ast_channel *chan, void *data)
ast_verbose(VERBOSE_PREFIX_4 "Announce Template:%s\n", template);
tpl_working = template;
tpl_current = strsep(&tpl_working, ":");
tpl_current=strsep(&tpl_working, ":");
while(tpl_current && looptemp < ARRAY_LEN(tmp)) {
while(tpl_current && looptemp < sizeof(tmp)) {
tmp[looptemp]=tpl_current;
looptemp++;
tpl_current = strsep(&tpl_working,":");
tpl_current=strsep(&tpl_working,":");
}
for(i = 0; i < looptemp; i++) {
for(i=0; i<looptemp; i++) {
ast_verbose(VERBOSE_PREFIX_4 "Announce:%s\n", tmp[i]);
if(!strcmp(tmp[i], "PARKED")) {
ast_say_digits(dchan, lot, "", dchan->language);
@@ -234,27 +237,45 @@ static int parkandannounce_exec(struct ast_channel *chan, void *data)
ast_stopstream(dchan);
ast_hangup(dchan);
finish:
ast_module_user_remove(u);
free(orig_s);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
/* return ast_register_application(app, park_exec); */
return ast_register_application(app, parkandannounce_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Call Parking and Announce Application");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,20 +19,18 @@
/*! \file
*
* \brief Trivial application to playback a sound file
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
@@ -43,9 +41,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/utils.h"
#include "asterisk/options.h"
#include "asterisk/app.h"
#include "asterisk/cli.h"
#include "asterisk/localtime.h"
#include "asterisk/say.h"
static char *tdesc = "Sound File Playback Application";
static char *app = "Playback";
@@ -65,329 +62,21 @@ static char *descrip =
"This application sets the following channel variable upon completion:\n"
" PLAYBACKSTATUS The status of the playback attempt as a text string, one of\n"
" SUCCESS | FAILED\n"
"See Also: Background (application) -- for playing soundfiles that are interruptible\n"
" WaitExten (application) -- wait for digits from caller, optionally play music on hold\n"
;
STANDARD_LOCAL_USER;
static struct ast_config *say_cfg = NULL;
/* save the say' api calls.
* The first entry is NULL if we have the standard source,
* otherwise we are sourcing from here.
* 'say load [new|old]' will enable the new or old method, or report status
*/
static const void * say_api_buf[40];
static const char *say_old = "old";
static const char *say_new = "new";
static void save_say_mode(const void *arg)
{
int i = 0;
say_api_buf[i++] = arg;
say_api_buf[i++] = ast_say_number_full;
say_api_buf[i++] = ast_say_enumeration_full;
say_api_buf[i++] = ast_say_digit_str_full;
say_api_buf[i++] = ast_say_character_str_full;
say_api_buf[i++] = ast_say_phonetic_str_full;
say_api_buf[i++] = ast_say_datetime;
say_api_buf[i++] = ast_say_time;
say_api_buf[i++] = ast_say_date;
say_api_buf[i++] = ast_say_datetime_from_now;
say_api_buf[i++] = ast_say_date_with_format;
}
static void restore_say_mode(void *arg)
{
int i = 0;
say_api_buf[i++] = arg;
ast_say_number_full = say_api_buf[i++];
ast_say_enumeration_full = say_api_buf[i++];
ast_say_digit_str_full = say_api_buf[i++];
ast_say_character_str_full = say_api_buf[i++];
ast_say_phonetic_str_full = say_api_buf[i++];
ast_say_datetime = say_api_buf[i++];
ast_say_time = say_api_buf[i++];
ast_say_date = say_api_buf[i++];
ast_say_datetime_from_now = say_api_buf[i++];
ast_say_date_with_format = say_api_buf[i++];
}
/*
* Typical 'say' arguments in addition to the date or number or string
* to say. We do not include 'options' because they may be different
* in recursive calls, and so they are better left as an external
* parameter.
*/
typedef struct {
struct ast_channel *chan;
const char *ints;
const char *language;
int audiofd;
int ctrlfd;
} say_args_t;
static int s_streamwait3(const say_args_t *a, const char *fn)
{
int res = ast_streamfile(a->chan, fn, a->language);
if (res) {
ast_log(LOG_WARNING, "Unable to play message %s\n", fn);
return res;
}
res = (a->audiofd > -1 && a->ctrlfd > -1) ?
ast_waitstream_full(a->chan, a->ints, a->audiofd, a->ctrlfd) :
ast_waitstream(a->chan, a->ints);
ast_stopstream(a->chan);
return res;
}
/*
* the string is 'prefix:data' or prefix:fmt:data'
* with ':' being invalid in strings.
*/
static int do_say(say_args_t *a, const char *s, const char *options, int depth)
{
struct ast_variable *v;
char *lang, *x, *rule = NULL;
int ret = 0;
struct varshead head = { .first = NULL, .last = NULL };
struct ast_var_t *n;
if (depth++ > 10) {
ast_log(LOG_WARNING, "recursion too deep, exiting\n");
return -1;
} else if (!say_cfg) {
ast_log(LOG_WARNING, "no say.conf, cannot spell '%s'\n", s);
return -1;
}
/* scan languages same as in file.c */
if (a->language == NULL)
a->language = "en"; /* default */
lang = ast_strdupa(a->language);
for (;;) {
for (v = ast_variable_browse(say_cfg, lang); v ; v = v->next) {
if (ast_extension_match(v->name, s)) {
rule = ast_strdupa(v->value);
break;
}
}
if (rule)
break;
if ( (x = strchr(lang, '_')) )
*x = '\0'; /* try without suffix */
else if (strcmp(lang, "en"))
lang = "en"; /* last resort, try 'en' if not done yet */
else
break;
}
if (!rule)
return 0;
/* skip up to two prefixes to get the value */
if ( (x = strchr(s, ':')) )
s = x + 1;
if ( (x = strchr(s, ':')) )
s = x + 1;
n = ast_var_assign("SAY", s);
AST_LIST_INSERT_HEAD(&head, n, entries);
/* scan the body, one piece at a time */
while ( !ret && (x = strsep(&rule, ",")) ) { /* exit on key */
char fn[128];
const char *p, *fmt, *data; /* format and data pointers */
/* prepare a decent file name */
x = ast_skip_blanks(x);
ast_trim_blanks(x);
/* replace variables */
memset(fn, 0, sizeof(fn)); /* XXX why isn't done in pbx_substitute_variables_helper! */
pbx_substitute_variables_varshead(&head, x, fn, sizeof(fn));
/* locate prefix and data, if any */
fmt = index(fn, ':');
if (!fmt || fmt == fn) { /* regular filename */
ret = s_streamwait3(a, fn);
continue;
}
fmt++;
data = index(fmt, ':'); /* colon before data */
if (!data || data == fmt) { /* simple prefix-fmt */
ret = do_say(a, fn, options, depth);
continue;
}
/* prefix:fmt:data */
for (p = fmt; p < data && ret <= 0; p++) {
char fn2[sizeof(fn)];
if (*p == ' ' || *p == '\t') /* skip blanks */
continue;
if (*p == '\'') {/* file name - we trim them */
char *y;
strcpy(fn2, ast_skip_blanks(p+1)); /* make a full copy */
y = index(fn2, '\'');
if (!y) {
p = data; /* invalid. prepare to end */
break;
}
*y = '\0';
ast_trim_blanks(fn2);
p = index(p+1, '\'');
ret = s_streamwait3(a, fn2);
} else {
int l = fmt-fn;
strcpy(fn2, fn); /* copy everything */
/* after prefix, append the format */
fn2[l++] = *p;
strcpy(fn2 + l, data);
ret = do_say(a, fn2, options, depth);
}
if (ret) {
break;
}
}
}
ast_var_delete(n);
return ret;
}
static int say_full(struct ast_channel *chan, const char *string,
const char *ints, const char *lang, const char *options,
int audiofd, int ctrlfd)
{
say_args_t a = { chan, ints, lang, audiofd, ctrlfd };
return do_say(&a, string, options, 0);
}
static int say_number_full(struct ast_channel *chan, int num,
const char *ints, const char *lang, const char *options,
int audiofd, int ctrlfd)
{
char buf[64];
say_args_t a = { chan, ints, lang, audiofd, ctrlfd };
snprintf(buf, sizeof(buf), "num:%d", num);
return do_say(&a, buf, options, 0);
}
static int say_enumeration_full(struct ast_channel *chan, int num,
const char *ints, const char *lang, const char *options,
int audiofd, int ctrlfd)
{
char buf[64];
say_args_t a = { chan, ints, lang, audiofd, ctrlfd };
snprintf(buf, sizeof(buf), "enum:%d", num);
return do_say(&a, buf, options, 0);
}
static int say_date_generic(struct ast_channel *chan, time_t t,
const char *ints, const char *lang, const char *format, const char *timezone, const char *prefix)
{
char buf[128];
struct tm tm;
say_args_t a = { chan, ints, lang, -1, -1 };
if (format == NULL)
format = "";
ast_localtime(&t, &tm, NULL);
snprintf(buf, sizeof(buf), "%s:%s:%04d%02d%02d%02d%02d.%02d-%d-%3d",
prefix,
format,
tm.tm_year+1900,
tm.tm_mon+1,
tm.tm_mday,
tm.tm_hour,
tm.tm_min,
tm.tm_sec,
tm.tm_wday,
tm.tm_yday);
return do_say(&a, buf, NULL, 0);
}
static int say_date_with_format(struct ast_channel *chan, time_t t,
const char *ints, const char *lang, const char *format, const char *timezone)
{
return say_date_generic(chan, t, ints, lang, format, timezone, "datetime");
}
static int say_date(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
{
return say_date_generic(chan, t, ints, lang, "", NULL, "date");
}
static int say_time(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
{
return say_date_generic(chan, t, ints, lang, "", NULL, "time");
}
static int say_datetime(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
{
return say_date_generic(chan, t, ints, lang, "", NULL, "datetime");
}
/*
* remap the 'say' functions to use those in this file
*/
static int __say_init(int fd, int argc, char *argv[])
{
const char *old_mode = say_api_buf[0] ? say_new : say_old;
char *mode;
if (argc == 2) {
ast_cli(fd, "say mode is [%s]\n", old_mode);
return RESULT_SUCCESS;
} else if (argc != 3)
return RESULT_SHOWUSAGE;
mode = argv[2];
ast_log(LOG_WARNING, "init say.c from %s to %s\n", old_mode, mode);
if (!strcmp(mode, old_mode)) {
ast_log(LOG_WARNING, "say mode is %s already\n", mode);
} else if (!strcmp(mode, say_new)) {
if (say_cfg == NULL)
say_cfg = ast_config_load("say.conf");
save_say_mode(say_new);
ast_say_number_full = say_number_full;
ast_say_enumeration_full = say_enumeration_full;
#if 0
ast_say_digits_full = say_digits_full;
ast_say_digit_str_full = say_digit_str_full;
ast_say_character_str_full = say_character_str_full;
ast_say_phonetic_str_full = say_phonetic_str_full;
ast_say_datetime_from_now = say_datetime_from_now;
#endif
ast_say_datetime = say_datetime;
ast_say_time = say_time;
ast_say_date = say_date;
ast_say_date_with_format = say_date_with_format;
} else if (!strcmp(mode, say_old) && say_api_buf[0] == say_new) {
restore_say_mode(NULL);
} else {
ast_log(LOG_WARNING, "unrecognized mode %s\n", mode);
}
return RESULT_SUCCESS;
}
static struct ast_cli_entry cli_playback[] = {
{ { "say", "load", NULL },
__say_init, "set/show the say mode",
"Usage: say load [new|old]\n Set/show the say mode\n" },
};
LOCAL_USER_DECL;
static int playback_exec(struct ast_channel *chan, void *data)
{
int res = 0;
int mres = 0;
struct ast_module_user *u;
char *tmp;
int res = 0, mres = 0;
struct localuser *u;
char *tmp = NULL;
int option_skip=0;
int option_say=0;
int option_noanswer = 0;
char *front = NULL, *back = NULL;
int priority_jump = 0;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(filenames);
AST_APP_ARG(options);
@@ -398,16 +87,20 @@ static int playback_exec(struct ast_channel *chan, void *data)
return -1;
}
tmp = ast_strdupa(data);
LOCAL_USER_ADD(u);
tmp = ast_strdupa(data);
if (!tmp) {
ast_log(LOG_ERROR, "Out of memory!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
u = ast_module_user_add(chan);
AST_STANDARD_APP_ARGS(args, tmp);
if (args.options) {
if (strcasestr(args.options, "skip"))
option_skip = 1;
if (strcasestr(args.options, "say"))
option_say = 1;
if (strcasestr(args.options, "noanswer"))
option_noanswer = 1;
if (strchr(args.options, 'j'))
@@ -417,78 +110,71 @@ static int playback_exec(struct ast_channel *chan, void *data)
if (chan->_state != AST_STATE_UP) {
if (option_skip) {
/* At the user's option, skip if the line is not up */
goto done;
LOCAL_USER_REMOVE(u);
return 0;
} else if (!option_noanswer)
/* Otherwise answer unless we're supposed to send this while on-hook */
res = ast_answer(chan);
}
if (!res) {
char *back = args.filenames;
char *front;
ast_stopstream(chan);
while (!res && (front = strsep(&back, "&"))) {
if (option_say)
res = say_full(chan, front, "", chan->language, NULL, -1, -1);
else
res = ast_streamfile(chan, front, chan->language);
front = tmp;
while (!res && front) {
if ((back = strchr(front, '&'))) {
*back = '\0';
back++;
}
res = ast_streamfile(chan, front, chan->language);
if (!res) {
res = ast_waitstream(chan, "");
ast_stopstream(chan);
} else {
ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char *)data);
if (priority_jump || ast_opt_priority_jumping)
if (priority_jump || option_priority_jumping)
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
res = 0;
mres = 1;
}
front = back;
}
if (mres)
pbx_builtin_setvar_helper(chan, "PLAYBACKSTATUS", "FAILED");
else
pbx_builtin_setvar_helper(chan, "PLAYBACKSTATUS", "SUCCESS");
}
done:
pbx_builtin_setvar_helper(chan, "PLAYBACKSTATUS", mres ? "FAILED" : "SUCCESS");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return res;
}
static int reload(void)
{
if (say_cfg) {
ast_config_destroy(say_cfg);
ast_log(LOG_NOTICE, "Reloading say.conf\n");
}
say_cfg = ast_config_load("say.conf");
/*
* XXX here we should sort rules according to the same order
* we have in pbx.c so we have the same matching behaviour.
*/
return 0;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
ast_cli_unregister_multiple(cli_playback, sizeof(cli_playback) / sizeof(struct ast_cli_entry));
ast_module_user_hangup_all();
if (say_cfg)
ast_config_destroy(say_cfg);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
say_cfg = ast_config_load("say.conf");
ast_cli_register_multiple(cli_playback, sizeof(cli_playback) / sizeof(struct ast_cli_entry));
return ast_register_application(app, playback_exec, synopsis, descrip);
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Sound File Playback Application",
.load = load_module,
.unload = unload_module,
.reload = reload,
);
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,20 +19,18 @@
/*! \file
*
* \brief Block all calls without Caller*ID, require phone # to be entered
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/utils.h"
@@ -49,6 +47,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define PRIV_CONFIG "privacy.conf"
static char *tdesc = "Require phone number to be entered, if no CallerID sent";
static char *app = "PrivacyManager";
static char *synopsis = "Require phone number to be entered, if no CallerID sent";
@@ -74,6 +74,11 @@ static char *descrip =
" SUCCESS | FAILED \n"
;
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int privacy_exec (struct ast_channel *chan, void *data)
{
@@ -82,9 +87,9 @@ static int privacy_exec (struct ast_channel *chan, void *data)
int maxretries = 3;
int minlength = 10;
int x = 0;
const char *s;
char *s;
char phone[30];
struct ast_module_user *u;
struct localuser *u;
struct ast_config *cfg = NULL;
char *parse = NULL;
int priority_jump = 0;
@@ -94,8 +99,7 @@ static int privacy_exec (struct ast_channel *chan, void *data)
AST_APP_ARG(options);
);
u = ast_module_user_add(chan);
LOCAL_USER_ADD (u);
if (!ast_strlen_zero(chan->cid.cid_num)) {
if (option_verbose > 2)
ast_verbose (VERBOSE_PREFIX_3 "CallerID Present: Skipping\n");
@@ -104,13 +108,19 @@ static int privacy_exec (struct ast_channel *chan, void *data)
if (chan->_state != AST_STATE_UP) {
res = ast_answer(chan);
if (res) {
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
}
if (!ast_strlen_zero(data)) {
if (!ast_strlen_zero((char *)data))
{
parse = ast_strdupa(data);
if (!parse) {
ast_log(LOG_ERROR, "Out of memory!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
AST_STANDARD_APP_ARGS(args, parse);
@@ -183,24 +193,16 @@ static int privacy_exec (struct ast_channel *chan, void *data)
}
/*Got a number, play sounds and send them on their way*/
if ((retries < maxretries) && res >= 0 ) {
if ((retries < maxretries) && !res ) {
res = ast_streamfile(chan, "privacy-thankyou", chan->language);
if (!res)
res = ast_waitstream(chan, "");
ast_set_callerid (chan, phone, "Privacy Manager", NULL);
/* Clear the unavailable presence bit so if it came in on PRI
* the caller id will now be passed out to other channels
*/
chan->cid.cid_pres &= (AST_PRES_UNAVAILABLE ^ 0xFF);
if (option_verbose > 2) {
ast_verbose (VERBOSE_PREFIX_3 "Changed Caller*ID to %s, callerpres to %d\n",phone,chan->cid.cid_pres);
}
ast_set_callerid (chan, phone, "Privacy Manager", NULL);
if (option_verbose > 2)
ast_verbose (VERBOSE_PREFIX_3 "Changed Caller*ID to %s\n",phone);
pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "SUCCESS");
} else {
if (priority_jump || ast_opt_priority_jumping)
if (priority_jump || option_priority_jumping)
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "FAILED");
}
@@ -208,25 +210,45 @@ static int privacy_exec (struct ast_channel *chan, void *data)
ast_config_destroy(cfg);
}
ast_module_user_remove(u);
return 0;
LOCAL_USER_REMOVE (u);
return 0;
}
static int unload_module(void)
int
unload_module (void)
{
int res;
res = ast_unregister_application (app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int
load_module (void)
{
return ast_register_application (app, privacy_exec, synopsis, descrip);
return ast_register_application (app, privacy_exec, synopsis,
descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Require phone number to be entered, if no CallerID sent");
char *
description (void)
{
return tdesc;
}
int
usecount (void)
{
int res;
STANDARD_USECOUNT (res);
return res;
}
char *
key ()
{
return ASTERISK_GPL_KEY;
}

File diff suppressed because it is too large Load Diff

View File

@@ -23,15 +23,15 @@
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
@@ -39,7 +39,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/pbx.h"
#include "asterisk/module.h"
/*! \todo The Random() app should be removed from trunk following the release of 1.4 */
static char *tdesc = "Random goto";
static char *app_random = "Random";
@@ -47,62 +47,81 @@ static char *random_synopsis = "Conditionally branches, based upon a probability
static char *random_descrip =
"Random([probability]:[[context|]extension|]priority)\n"
" probability := INTEGER in the range 1 to 100\n"
"DEPRECATED: Use GotoIf($[${RAND(1,100)} > <number>]?<label>)\n";
" probability := INTEGER in the range 1 to 100\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static char random_state[256];
static int random_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct ast_module_user *u;
struct localuser *u;
char *s;
char *prob;
int probint;
static int deprecated = 0;
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Random requires an argument ([probability]:[[context|]extension|]priority)\n");
return -1;
}
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
s = ast_strdupa(data);
if (!s) {
ast_log(LOG_ERROR, "Out of memory!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
prob = strsep(&s,":");
if ((!prob) || (sscanf(prob, "%d", &probint) != 1))
probint = 0;
if (!deprecated) {
deprecated = 1;
ast_log(LOG_WARNING, "Random is deprecated in Asterisk 1.4. Replace with GotoIf($[${RAND(0,99)} + %d >= 100]?%s)\n", probint, s);
}
if ((ast_random() % 100) + probint >= 100) {
if ((random() % 100) + probint > 100) {
res = ast_parseable_goto(chan, s);
if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "Random branches to (%s,%s,%d)\n",
chan->context,chan->exten, chan->priority+1);
}
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app_random);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
initstate((getppid() * 65535 + getpid()) % RAND_MAX, random_state, 256);
return ast_register_application(app_random, random_exec, random_synopsis, random_descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Random goto");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,20 +19,18 @@
/*! \file
*
* \brief Trivial application to read a variable
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
@@ -43,19 +41,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/translate.h"
#include "asterisk/options.h"
#include "asterisk/utils.h"
#include "asterisk/indications.h"
enum {
OPT_SKIP = (1 << 0),
OPT_INDICATION = (1 << 1),
OPT_NOANSWER = (1 << 2),
} read_option_flags;
AST_APP_OPTIONS(read_app_options, {
AST_APP_OPTION('s', OPT_SKIP),
AST_APP_OPTION('i', OPT_INDICATION),
AST_APP_OPTION('n', OPT_NOANSWER),
});
static char *tdesc = "Read Variable Application";
static char *app = "Read";
@@ -65,131 +52,131 @@ static char *descrip =
" Read(variable[|filename][|maxdigits][|option][|attempts][|timeout])\n\n"
"Reads a #-terminated string of digits a certain number of times from the\n"
"user in to the given variable.\n"
" filename -- file to play before reading digits or tone with option i\n"
" filename -- file to play before reading digits.\n"
" maxdigits -- maximum acceptable number of digits. Stops reading after\n"
" maxdigits have been entered (without requiring the user to\n"
" press the '#' key).\n"
" Defaults to 0 - no limit - wait for the user press the '#' key.\n"
" Any value below 0 means the same. Max accepted value is 255.\n"
" option -- options are 's' , 'i', 'n'\n"
" 's' to return immediately if the line is not up,\n"
" 'i' to play filename as an indication tone from your indications.conf\n"
" 'n' to read digits even if the line is not up.\n"
" option -- may be 'skip' to return immediately if the line is not up,\n"
" or 'noanswer' to read digits even if the line is not up.\n"
" attempts -- if greater than 1, that many attempts will be made in the \n"
" event no data is entered.\n"
" timeout -- An integer number of seconds to wait for a digit response. If greater\n"
" than 0, that value will override the default timeout.\n\n"
" timeout -- if greater than 0, that value will override the default timeout.\n\n"
"Read should disconnect if the function fails or errors out.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
#define ast_next_data(instr,ptr,delim) if((ptr=strchr(instr,delim))) { *(ptr) = '\0' ; ptr++;}
static int read_exec(struct ast_channel *chan, void *data)
{
int res = 0;
struct ast_module_user *u;
char tmp[256] = "";
int maxdigits = 255;
int tries = 1, to = 0, x = 0;
struct localuser *u;
char tmp[256];
char *timeout = NULL;
char *varname = NULL;
char *filename = NULL;
char *loops;
char *maxdigitstr=NULL;
char *options=NULL;
int option_skip = 0;
int option_noanswer = 0;
int maxdigits=255;
int tries = 1;
int to = 0;
int x = 0;
char *argcopy = NULL;
struct tone_zone_sound *ts;
struct ast_flags flags = {0};
char *args[8];
AST_DECLARE_APP_ARGS(arglist,
AST_APP_ARG(variable);
AST_APP_ARG(filename);
AST_APP_ARG(maxdigits);
AST_APP_ARG(options);
AST_APP_ARG(attempts);
AST_APP_ARG(timeout);
);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Read requires an argument (variable)\n");
return -1;
}
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
argcopy = ast_strdupa(data);
AST_STANDARD_APP_ARGS(arglist, argcopy);
if (!ast_strlen_zero(arglist.options)) {
ast_app_parse_options(read_app_options, &flags, NULL, arglist.options);
if (!argcopy) {
ast_log(LOG_ERROR, "Out of memory\n");
LOCAL_USER_REMOVE(u);
return -1;
}
if (ast_app_separate_args(argcopy, '|', args, sizeof(args) / sizeof(args[0])) < 1) {
ast_log(LOG_WARNING, "Cannot Parse Arguments.\n");
LOCAL_USER_REMOVE(u);
return -1;
}
varname = args[x++];
filename = args[x++];
maxdigitstr = args[x++];
options = args[x++];
loops = args[x++];
timeout = args[x++];
if (!ast_strlen_zero(arglist.attempts)) {
tries = atoi(arglist.attempts);
if (tries <= 0)
if (options) {
if (!strcasecmp(options, "skip"))
option_skip = 1;
else if (!strcasecmp(options, "noanswer"))
option_noanswer = 1;
else {
if (strchr(options, 's'))
option_skip = 1;
if (strchr(options, 'n'))
option_noanswer = 1;
}
}
if(loops) {
tries = atoi(loops);
if(tries <= 0)
tries = 1;
}
if (!ast_strlen_zero(arglist.timeout)) {
to = atoi(arglist.timeout);
if(timeout) {
to = atoi(timeout);
if (to <= 0)
to = 0;
else
to *= 1000;
}
if (ast_strlen_zero(arglist.filename)) {
arglist.filename = NULL;
}
if (!ast_strlen_zero(arglist.maxdigits)) {
maxdigits = atoi(arglist.maxdigits);
if (ast_strlen_zero(filename))
filename = NULL;
if (maxdigitstr) {
maxdigits = atoi(maxdigitstr);
if ((maxdigits<1) || (maxdigits>255)) {
maxdigits = 255;
} else if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Accepting a maximum of %d digits.\n", maxdigits);
}
if (ast_strlen_zero(arglist.variable)) {
if (ast_strlen_zero(varname)) {
ast_log(LOG_WARNING, "Invalid! Usage: Read(variable[|filename][|maxdigits][|option][|attempts][|timeout])\n\n");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
ts=NULL;
if (ast_test_flag(&flags,OPT_INDICATION)) {
if (!ast_strlen_zero(arglist.filename)) {
ts = ast_get_indication_tone(chan->zone,arglist.filename);
}
}
if (chan->_state != AST_STATE_UP) {
if (ast_test_flag(&flags,OPT_SKIP)) {
if (option_skip) {
/* At the user's option, skip if the line is not up */
pbx_builtin_setvar_helper(chan, arglist.variable, "\0");
ast_module_user_remove(u);
pbx_builtin_setvar_helper(chan, varname, "\0");
LOCAL_USER_REMOVE(u);
return 0;
} else if (!ast_test_flag(&flags,OPT_NOANSWER)) {
} else if (!option_noanswer) {
/* Otherwise answer unless we're supposed to read while on-hook */
res = ast_answer(chan);
}
}
if (!res) {
while (tries && !res) {
while(tries && !res) {
ast_stopstream(chan);
if (ts && ts->data[0]) {
if (!to)
to = chan->pbx ? chan->pbx->rtimeout * 1000 : 6000;
res = ast_playtones_start(chan, 0, ts->data, 0);
for (x = 0; x < maxdigits; ) {
res = ast_waitfordigit(chan, to);
ast_playtones_stop(chan);
if (res < 1) {
tmp[x]='\0';
break;
}
tmp[x++] = res;
if (tmp[x-1] == '#') {
tmp[x-1] = '\0';
break;
}
}
} else {
res = ast_app_getdata(chan, arglist.filename, tmp, maxdigits, to);
}
res = ast_app_getdata(chan, filename, tmp, maxdigits, to);
if (res > -1) {
pbx_builtin_setvar_helper(chan, arglist.variable, tmp);
pbx_builtin_setvar_helper(chan, varname, tmp);
if (!ast_strlen_zero(tmp)) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "User entered '%s'\n", tmp);
@@ -205,30 +192,44 @@ static int read_exec(struct ast_channel *chan, void *data)
}
res = 0;
} else {
pbx_builtin_setvar_helper(chan, arglist.variable, tmp);
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "User disconnected\n");
}
}
}
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, read_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Read Variable Application");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -20,20 +20,18 @@
*
* \brief ReadFile application -- Reads in a File for you.
*
* \author Matt O'Gorman <mogorman@digium.com>
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
@@ -42,6 +40,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/app.h"
#include "asterisk/module.h"
static char *tdesc = "Stores output of file into a variable";
static char *app_readfile = "ReadFile";
static char *readfile_synopsis = "ReadFile(varname=file,length)";
@@ -52,11 +52,15 @@ static char *readfile_descrip =
" File - The name of the file to read.\n"
" Length - Maximum number of characters to capture.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int readfile_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct ast_module_user *u;
struct localuser *u;
char *s, *varname=NULL, *file=NULL, *length=NULL, *returnvar=NULL;
int len=0;
@@ -65,9 +69,14 @@ static int readfile_exec(struct ast_channel *chan, void *data)
return -1;
}
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
s = ast_strdupa(data);
if (!s) {
ast_log(LOG_ERROR, "Out of memory\n");
LOCAL_USER_REMOVE(u);
return -1;
}
varname = strsep(&s, "=");
file = strsep(&s, "|");
@@ -75,7 +84,7 @@ static int readfile_exec(struct ast_channel *chan, void *data)
if (!varname || !file) {
ast_log(LOG_ERROR, "No file or variable specified!\n");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
@@ -96,25 +105,40 @@ static int readfile_exec(struct ast_channel *chan, void *data)
pbx_builtin_setvar_helper(chan, varname, returnvar);
free(returnvar);
}
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app_readfile);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app_readfile, readfile_exec, readfile_synopsis, readfile_descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Stores output of file into a variable");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -20,22 +20,19 @@
/*! \file
*
* \brief RealTime App
*
* \author Anthony Minessale <anthmct@yahoo.com>
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
@@ -49,54 +46,50 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define next_one(var) var = var->next
#define crop_data(str) { *(str) = '\0' ; (str)++; }
static char *tdesc = "Realtime Data Lookup/Rewrite";
static char *app = "RealTime";
static char *uapp = "RealTimeUpdate";
static char *synopsis = "Realtime Data Lookup";
static char *usynopsis = "Realtime Data Rewrite";
static char *USAGE = "RealTime(<family>|<colmatch>|<value>[|<prefix>])";
static char *UUSAGE = "RealTimeUpdate(<family>|<colmatch>|<value>|<newcol>|<newval>)";
static char *desc =
"Use the RealTime config handler system to read data into channel variables.\n"
static char *desc = "Use the RealTime config handler system to read data into channel variables.\n"
"RealTime(<family>|<colmatch>|<value>[|<prefix>])\n\n"
"All unique column names will be set as channel variables with optional prefix\n"
"to the name. For example, a prefix of 'var_' would make the column 'name'\n"
"become the variable ${var_name}. REALTIMECOUNT will be set with the number\n"
"of values read.\n";
"All unique column names will be set as channel variables with optional prefix to the name.\n"
"e.g. prefix of 'var_' would make the column 'name' become the variable ${var_name}\n\n";
static char *udesc = "Use the RealTime config handler system to update a value\n"
"RealTimeUpdate(<family>|<colmatch>|<value>|<newcol>|<newval>)\n\n"
"The column <newcol> in 'family' matching column <colmatch>=<value> will be\n"
"updated to <newval>. REALTIMECOUNT will be set with the number of rows\n"
"updated or -1 if an error occurs.\n";
"The column <newcol> in 'family' matching column <colmatch>=<value> will be updated to <newval>\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int cli_realtime_load(int fd, int argc, char **argv)
static int cli_load_realtime(int fd, int argc, char **argv)
{
char *header_format = "%30s %-30s\n";
struct ast_variable *var = NULL, *save = NULL;
struct ast_variable *var=NULL;
if (argc < 5) {
if(argc<5) {
ast_cli(fd, "You must supply a family name, a column to match on, and a value to match to.\n");
return RESULT_FAILURE;
}
var = ast_load_realtime(argv[2], argv[3], argv[4], NULL);
if (var) {
save = var;
if(var) {
ast_cli(fd, header_format, "Column Name", "Column Value");
ast_cli(fd, header_format, "--------------------", "--------------------");
while (var) {
while(var) {
ast_cli(fd, header_format, var->name, var->value);
var = var->next;
}
ast_variables_destroy(save);
} else {
ast_cli(fd, "No rows found matching search criteria.\n");
}
return RESULT_SUCCESS;
}
static int cli_realtime_update(int fd, int argc, char **argv) {
static int cli_update_realtime(int fd, int argc, char **argv) {
int res = 0;
if(argc<7) {
@@ -117,49 +110,45 @@ static int cli_realtime_update(int fd, int argc, char **argv) {
return RESULT_SUCCESS;
}
static char cli_realtime_load_usage[] =
static char cli_load_realtime_usage[] =
"Usage: realtime load <family> <colmatch> <value>\n"
" Prints out a list of variables using the RealTime driver.\n";
static char cli_realtime_update_usage[] =
static struct ast_cli_entry cli_load_realtime_cmd = {
{ "realtime", "load", NULL, NULL }, cli_load_realtime,
"Used to print out RealTime variables.", cli_load_realtime_usage, NULL };
static char cli_update_realtime_usage[] =
"Usage: realtime update <family> <colmatch> <value>\n"
" Update a single variable using the RealTime driver.\n";
static struct ast_cli_entry cli_realtime[] = {
{ { "realtime", "load", NULL, NULL },
cli_realtime_load, "Used to print out RealTime variables.",
cli_realtime_load_usage, NULL },
{ { "realtime", "update", NULL, NULL },
cli_realtime_update, "Used to update RealTime variables.",
cli_realtime_update_usage, NULL },
};
static struct ast_cli_entry cli_update_realtime_cmd = {
{ "realtime", "update", NULL, NULL }, cli_update_realtime,
"Used to update RealTime variables.", cli_update_realtime_usage, NULL };
static int realtime_update_exec(struct ast_channel *chan, void *data)
{
char *family=NULL, *colmatch=NULL, *value=NULL, *newcol=NULL, *newval=NULL;
struct ast_module_user *u;
int res = 0, count = 0;
char countc[13];
ast_log(LOG_WARNING, "The RealTimeUpdate application has been deprecated in favor of the REALTIME dialplan function.\n");
struct localuser *u;
int res = 0;
if (ast_strlen_zero(data)) {
ast_log(LOG_ERROR,"Invalid input: usage %s\n",UUSAGE);
return -1;
}
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
family = ast_strdupa(data);
if ((colmatch = strchr(family,'|'))) {
crop_data(colmatch);
if ((value = strchr(colmatch,'|'))) {
crop_data(value);
if ((newcol = strchr(value,'|'))) {
crop_data(newcol);
if ((newval = strchr(newcol,'|')))
crop_data(newval);
if ((family = ast_strdupa(data))) {
if ((colmatch = strchr(family,'|'))) {
crop_data(colmatch);
if ((value = strchr(colmatch,'|'))) {
crop_data(value);
if ((newcol = strchr(value,'|'))) {
crop_data(newcol);
if ((newval = strchr(newcol,'|')))
crop_data(newval);
}
}
}
}
@@ -167,13 +156,10 @@ static int realtime_update_exec(struct ast_channel *chan, void *data)
ast_log(LOG_ERROR,"Invalid input: usage %s\n",UUSAGE);
res = -1;
} else {
count = ast_update_realtime(family,colmatch,value,newcol,newval,NULL);
ast_update_realtime(family,colmatch,value,newcol,newval,NULL);
}
snprintf(countc, sizeof(countc), "%d", count);
pbx_builtin_setvar_helper(chan, "REALTIMECOUNT", countc);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return res;
}
@@ -181,29 +167,27 @@ static int realtime_update_exec(struct ast_channel *chan, void *data)
static int realtime_exec(struct ast_channel *chan, void *data)
{
int res=0, count=0;
struct ast_module_user *u;
int res=0;
struct localuser *u;
struct ast_variable *var, *itt;
char *family=NULL, *colmatch=NULL, *value=NULL, *prefix=NULL, *vname=NULL;
char countc[13];
size_t len;
ast_log(LOG_WARNING, "The RealTime application has been deprecated in favor of the REALTIME dialplan function.\n");
if (ast_strlen_zero(data)) {
ast_log(LOG_ERROR,"Invalid input: usage %s\n",USAGE);
return -1;
}
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
family = ast_strdupa(data);
if ((colmatch = strchr(family,'|'))) {
crop_data(colmatch);
if ((value = strchr(colmatch,'|'))) {
crop_data(value);
if ((prefix = strchr(value,'|')))
crop_data(prefix);
if ((family = ast_strdupa(data))) {
if ((colmatch = strchr(family,'|'))) {
crop_data(colmatch);
if ((value = strchr(colmatch,'|'))) {
crop_data(value);
if ((prefix = strchr(value,'|')))
crop_data(prefix);
}
}
}
if (! (family && value && colmatch) ) {
@@ -223,41 +207,56 @@ static int realtime_exec(struct ast_channel *chan, void *data)
vname = itt->name;
pbx_builtin_setvar_helper(chan, vname, itt->value);
count++;
}
ast_variables_destroy(var);
} else if (option_verbose > 3)
ast_verbose(VERBOSE_PREFIX_4"No Realtime Matches Found.\n");
}
snprintf(countc, sizeof(countc), "%d", count);
pbx_builtin_setvar_helper(chan, "REALTIMECOUNT", countc);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
ast_cli_unregister_multiple(cli_realtime, sizeof(cli_realtime) / sizeof(struct ast_cli_entry));
res = ast_unregister_application(uapp);
res = ast_cli_unregister(&cli_load_realtime_cmd);
res |= ast_cli_unregister(&cli_update_realtime_cmd);
res |= ast_unregister_application(uapp);
res |= ast_unregister_application(app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
int res;
ast_cli_register_multiple(cli_realtime, sizeof(cli_realtime) / sizeof(struct ast_cli_entry));
res = ast_register_application(uapp, realtime_update_exec, usynopsis, udesc);
res = ast_cli_register(&cli_load_realtime_cmd);
res |= ast_cli_register(&cli_update_realtime_cmd);
res |= ast_register_application(uapp, realtime_update_exec, usynopsis, udesc);
res |= ast_register_application(app, realtime_exec, synopsis, desc);
return res;
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Realtime Data Lookup/Rewrite");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -20,19 +20,17 @@
*
* \brief Trivial application to record a sound file
*
* \author Matthew Fredrickson <creslin@digium.com>
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
@@ -43,8 +41,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/dsp.h"
#include "asterisk/utils.h"
#include "asterisk/options.h"
#include "asterisk/app.h"
static char *tdesc = "Trivial Record Application";
static char *app = "Record";
@@ -63,17 +61,18 @@ static char *descrip =
" 'n' : do not answer, but record anyway if line not yet answered\n"
" 'q' : quiet (do not play a beep tone)\n"
" 's' : skip recording if the line is not yet answered\n"
" 't' : use alternate '*' terminator key (DTMF) instead of default '#'\n"
" 'x' : ignore all terminator keys (DTMF) and keep recording until hangup\n"
" 't' : use alternate '*' terminator key instead of default '#'\n"
"\n"
"If filename contains '%d', these characters will be replaced with a number\n"
"incremented by one each time the file is recorded. A channel variable\n"
"named RECORDED_FILE will also be set, which contains the final filemname.\n\n"
"Use 'core show file formats' to see the available formats on your system\n\n"
"incremented by one each time the file is recorded. \n\n"
"Use 'show file formats' to see the available formats on your system\n\n"
"User can press '#' to terminate the recording and continue to the next priority.\n\n"
"If the user should hangup during a recording, all data will be lost and the\n"
"application will teminate. \n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int record_exec(struct ast_channel *chan, void *data)
{
@@ -86,7 +85,7 @@ static int record_exec(struct ast_channel *chan, void *data)
char tmp[256];
struct ast_filestream *s = '\0';
struct ast_module_user *u;
struct localuser *u;
struct ast_frame *f = NULL;
struct ast_dsp *sildet = NULL; /* silence detector dsp */
@@ -112,10 +111,15 @@ static int record_exec(struct ast_channel *chan, void *data)
return -1;
}
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
/* Yay for strsep being easy */
vdata = ast_strdupa(data);
if (!vdata) {
ast_log(LOG_ERROR, "Out of memory\n");
LOCAL_USER_REMOVE(u);
return -1;
}
p = vdata;
filename = strsep(&p, "|");
@@ -136,7 +140,7 @@ static int record_exec(struct ast_channel *chan, void *data)
}
if (!ext) {
ast_log(LOG_WARNING, "No extension specified to filename!\n");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
if (silstr) {
@@ -169,8 +173,6 @@ static int record_exec(struct ast_channel *chan, void *data)
option_append = 1;
if (strchr(options, 't'))
terminator = '*';
if (strchr(options, 'x'))
terminator = 0;
if (strchr(options, 'q'))
option_quiet = 1;
}
@@ -181,39 +183,13 @@ static int record_exec(struct ast_channel *chan, void *data)
/* these are to allow the use of the %d in the config file for a wild card of sort to
create a new file with the inputed name scheme */
if (percentflag) {
AST_DECLARE_APP_ARGS(fname,
AST_APP_ARG(piece)[100];
);
char *tmp2 = ast_strdupa(filename);
char countstring[15];
int i;
/* Separate each piece out by the format specifier */
AST_NONSTANDARD_APP_ARGS(fname, tmp2, '%');
do {
int tmplen;
/* First piece has no leading percent, so it's copied verbatim */
ast_copy_string(tmp, fname.piece[0], sizeof(tmp));
tmplen = strlen(tmp);
for (i = 1; i < fname.argc; i++) {
if (fname.piece[i][0] == 'd') {
/* Substitute the count */
snprintf(countstring, sizeof(countstring), "%d", count);
ast_copy_string(tmp + tmplen, countstring, sizeof(tmp) - tmplen);
tmplen += strlen(countstring);
} else if (tmplen + 2 < sizeof(tmp)) {
/* Unknown format specifier - just copy it verbatim */
tmp[tmplen++] = '%';
tmp[tmplen++] = fname.piece[i][0];
}
/* Copy the remaining portion of the piece */
ast_copy_string(tmp + tmplen, &(fname.piece[i][1]), sizeof(tmp) - tmplen);
}
snprintf(tmp, sizeof(tmp), filename, count);
count++;
} while (ast_fileexists(tmp, ext, chan->language) > 0);
} while ( ast_fileexists(tmp, ext, chan->language) != -1 );
pbx_builtin_setvar_helper(chan, "RECORDED_FILE", tmp);
} else
ast_copy_string(tmp, filename, sizeof(tmp));
strncpy(tmp, filename, sizeof(tmp)-1);
/* end of routine mentioned */
@@ -221,7 +197,7 @@ static int record_exec(struct ast_channel *chan, void *data)
if (chan->_state != AST_STATE_UP) {
if (option_skip) {
/* At the user's option, skip if the line is not up */
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return 0;
} else if (!option_noanswer) {
/* Otherwise answer unless we're supposed to record while on-hook */
@@ -252,13 +228,13 @@ static int record_exec(struct ast_channel *chan, void *data)
res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
sildet = ast_dsp_new();
if (!sildet) {
ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
ast_dsp_set_threshold(sildet, 256);
@@ -273,7 +249,7 @@ static int record_exec(struct ast_channel *chan, void *data)
goto out;
}
if (ast_opt_transmit_silence)
if (option_transmit_silence_during_record)
silgen = ast_channel_start_silence_generator(chan);
/* Request a video update */
@@ -362,25 +338,40 @@ static int record_exec(struct ast_channel *chan, void *data)
ast_dsp_free(sildet);
}
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, record_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Trivial Record Application");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,7 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (c) 2003, 2006 Tilghman Lesher. All rights reserved.
* Copyright (c) 2006 Digium, Inc.
* Copyright (c) 2003 Tilghman Lesher. All rights reserved.
*
* Tilghman Lesher <app_sayunixtime__200309@the-tilghman.com>
*
@@ -19,21 +18,19 @@
/*! \file
*
* \brief SayUnixTime application
*
* \author Tilghman Lesher <app_sayunixtime__200309@the-tilghman.com>
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
@@ -41,7 +38,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/say.h"
#include "asterisk/app.h"
static char *tdesc = "Say time";
static char *app_sayunixtime = "SayUnixTime";
static char *app_datetime = "DateTime";
@@ -65,55 +64,78 @@ static char *datetime_descrip =
" format: a format the time is to be said in. See voicemail.conf.\n"
" defaults to \"ABdY 'digits/at' IMp\"\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int sayunixtime_exec(struct ast_channel *chan, void *data)
{
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(timeval);
AST_APP_ARG(timezone);
AST_APP_ARG(format);
);
char *parse;
int res = 0;
struct ast_module_user *u;
int res=0;
struct localuser *u;
char *s,*zone=NULL,*timec,*format;
time_t unixtime;
struct timeval tv;
if (!data)
return 0;
LOCAL_USER_ADD(u);
parse = ast_strdupa(data);
tv = ast_tvnow();
unixtime = (time_t)tv.tv_sec;
u = ast_module_user_add(chan);
if( !strcasecmp(chan->language, "da" ) ) {
format = "A dBY HMS";
} else if ( !strcasecmp(chan->language, "de" ) ) {
format = "A dBY HMS";
} else {
format = "ABdY 'digits/at' IMp";
}
AST_STANDARD_APP_ARGS(args, parse);
if (data) {
s = data;
s = ast_strdupa(s);
if (s) {
timec = strsep(&s,"|");
if ((timec) && (*timec != '\0')) {
long timein;
if (sscanf(timec,"%ld",&timein) == 1) {
unixtime = (time_t)timein;
}
}
if (s) {
zone = strsep(&s,"|");
if (zone && (*zone == '\0'))
zone = NULL;
if (s) {
format = s;
}
}
} else {
ast_log(LOG_ERROR, "Out of memory error\n");
}
}
ast_get_time_t(args.timeval, &unixtime, time(NULL), NULL);
if (chan->_state != AST_STATE_UP)
if (chan->_state != AST_STATE_UP) {
res = ast_answer(chan);
}
if (!res)
res = ast_say_date_with_format(chan, unixtime, AST_DIGIT_ANY,
chan->language, args.format, args.timezone);
ast_module_user_remove(u);
res = ast_say_date_with_format(chan, unixtime, AST_DIGIT_ANY, chan->language, format, zone);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app_sayunixtime);
res |= ast_unregister_application(app_datetime);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
int res;
@@ -123,4 +145,19 @@ static int load_module(void)
return res;
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Say time");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,20 +19,18 @@
/*! \file
*
* \brief App to send DTMF digits
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
@@ -43,7 +41,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/options.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"
#include "asterisk/manager.h"
static char *tdesc = "Send DTMF digits Application";
static char *app = "SendDTMF";
@@ -55,11 +54,14 @@ static char *descrip =
" The application will either pass the assigned digits or terminate if it\n"
" encounters an error.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int senddtmf_exec(struct ast_channel *chan, void *data)
{
int res = 0;
struct ast_module_user *u;
struct localuser *u;
char *digits = NULL, *to = NULL;
int timeout = 250;
@@ -68,9 +70,14 @@ static int senddtmf_exec(struct ast_channel *chan, void *data)
return 0;
}
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
digits = ast_strdupa(data);
if (!digits) {
ast_log(LOG_ERROR, "Out of Memory!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
if ((to = strchr(digits,'|'))) {
*to = '\0';
@@ -78,66 +85,45 @@ static int senddtmf_exec(struct ast_channel *chan, void *data)
timeout = atoi(to);
}
if (timeout <= 0)
if(timeout <= 0)
timeout = 250;
res = ast_dtmf_stream(chan,NULL,digits,timeout);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return res;
}
static char mandescr_playdtmf[] =
"Description: Plays a dtmf digit on the specified channel.\n"
"Variables: (all are required)\n"
" Channel: Channel name to send digit to\n"
" Digit: The dtmf digit to play\n";
static int manager_play_dtmf(struct mansession *s, const struct message *m)
{
const char *channel = astman_get_header(m, "Channel");
const char *digit = astman_get_header(m, "Digit");
struct ast_channel *chan = ast_get_channel_by_name_locked(channel);
if (!chan) {
astman_send_error(s, m, "Channel not specified");
return 0;
}
if (!digit) {
astman_send_error(s, m, "No digit specified");
ast_mutex_unlock(&chan->lock);
return 0;
}
ast_senddigit(chan, *digit);
ast_mutex_unlock(&chan->lock);
astman_send_ack(s, m, "DTMF successfully queued");
return 0;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
res |= ast_manager_unregister("PlayDTMF");
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, senddtmf_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
res = ast_manager_register2( "PlayDTMF", EVENT_FLAG_CALL, manager_play_dtmf, "Play DTMF signal on a specific channel.", mandescr_playdtmf );
res |= ast_register_application(app, senddtmf_exec, synopsis, descrip);
STANDARD_USECOUNT(res);
return res;
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Send DTMF digits Application");
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,22 +19,20 @@
/*! \file
*
* \brief App to transmit a text message
*
* \author Mark Spencer <markster@digium.com>
*
* \note Requires support of sending text messages from channel driver
* Requires support of sending text messages from channel driver
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
@@ -46,6 +44,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/options.h"
#include "asterisk/app.h"
static const char *tdesc = "Send Text Applications";
static const char *app = "SendText";
static const char *synopsis = "Send a Text Message";
@@ -63,11 +63,14 @@ static const char *descrip =
"'j' -- jump to n+101 priority if the channel doesn't support\n"
" text transport\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int sendtext_exec(struct ast_channel *chan, void *data)
{
int res = 0;
struct ast_module_user *u;
struct localuser *u;
char *status = "UNSUPPORTED";
char *parse = NULL;
int priority_jump = 0;
@@ -76,14 +79,20 @@ static int sendtext_exec(struct ast_channel *chan, void *data)
AST_APP_ARG(options);
);
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "SendText requires an argument (text[|options])\n");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
} else
} else {
parse = ast_strdupa(data);
if (!parse) {
ast_log(LOG_ERROR, "Out of memory!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
}
AST_STANDARD_APP_ARGS(args, parse);
@@ -92,40 +101,56 @@ static int sendtext_exec(struct ast_channel *chan, void *data)
priority_jump = 1;
}
ast_channel_lock(chan);
ast_mutex_lock(&chan->lock);
if (!chan->tech->send_text) {
ast_channel_unlock(chan);
pbx_builtin_setvar_helper(chan, "SENDTEXTSTATUS", status);
ast_mutex_unlock(&chan->lock);
/* Does not support transport */
if (priority_jump || ast_opt_priority_jumping)
if (priority_jump || option_priority_jumping)
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return 0;
}
status = "FAILURE";
ast_channel_unlock(chan);
ast_mutex_unlock(&chan->lock);
res = ast_sendtext(chan, args.text);
if (!res)
status = "SUCCESS";
pbx_builtin_setvar_helper(chan, "SENDTEXTSTATUS", status);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return 0;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, sendtext_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Send Text Applications");
char *description(void)
{
return (char *) tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,20 +19,18 @@
/*! \file
*
* \brief App to set callerid
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
@@ -47,6 +45,9 @@ static char *app2 = "SetCallerPres";
static char *synopsis2 = "Set CallerID Presentation";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static char *descrip2 =
" SetCallerPres(presentation): Set Caller*ID presentation on a call.\n"
@@ -66,28 +67,29 @@ static char *descrip2 =
static int setcallerid_pres_exec(struct ast_channel *chan, void *data)
{
struct ast_module_user *u;
struct localuser *u;
int pres = -1;
u = ast_module_user_add(chan);
/* For interface consistency, permit the argument to be specified as a number */
if (sscanf(data, "%d", &pres) != 1 || pres < 0 || pres > 255 || (pres & 0x9c)) {
pres = ast_parse_caller_presentation(data);
}
LOCAL_USER_ADD(u);
pres = ast_parse_caller_presentation(data);
if (pres < 0) {
ast_log(LOG_WARNING, "'%s' is not a valid presentation (see 'show application SetCallerPres')\n",
(char *) data);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return 0;
}
chan->cid.cid_pres = pres;
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return 0;
}
static char *tdesc = "Set CallerID Application";
static char *app = "SetCallerID";
static char *synopsis = "Set CallerID";
@@ -102,24 +104,23 @@ static int setcallerid_exec(struct ast_channel *chan, void *data)
char *tmp = NULL;
char name[256];
char num[256];
struct ast_module_user *u;
struct localuser *u;
char *opt;
int anitoo = 0;
static int dep_warning = 0;
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "SetCallerID requires an argument!\n");
return 0;
}
u = ast_module_user_add(chan);
if (!dep_warning) {
dep_warning = 1;
ast_log(LOG_WARNING, "SetCallerID is deprecated. Please use Set(CALLERID(all)=...) or Set(CALLERID(ani)=...) instead.\n");
}
LOCAL_USER_ADD(u);
tmp = ast_strdupa(data);
if (!tmp) {
ast_log(LOG_ERROR, "Out of memory\n");
LOCAL_USER_REMOVE(u);
return -1;
}
opt = strchr(tmp, '|');
if (opt) {
@@ -132,24 +133,24 @@ static int setcallerid_exec(struct ast_channel *chan, void *data)
ast_callerid_split(tmp, name, sizeof(name), num, sizeof(num));
ast_set_callerid(chan, num, name, anitoo ? num : NULL);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app2);
res |= ast_unregister_application(app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
int res;
@@ -159,4 +160,19 @@ static int load_module(void)
return res;
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Set CallerID Application");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,20 +19,18 @@
/*! \file
*
* \brief Applictions connected with CDR engine
*
* \author Justin Huff <jjhuff@mspin.net>
*
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/channel.h"
#include "asterisk/cdr.h"
#include "asterisk/module.h"
@@ -43,6 +41,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/utils.h"
static char *tdesc = "CDR user field apps";
static char *setcdruserfield_descrip =
"[Synopsis]\n"
"SetCDRUserField(value)\n\n"
@@ -52,8 +52,7 @@ static char *setcdruserfield_descrip =
" can use for data not stored anywhere else in the record.\n"
" CDR records can be used for billing or storing other arbitrary data\n"
" (I.E. telephone survey responses)\n"
" Also see AppendCDRUserField().\n"
"\nThis application is deprecated in favor of Set(CDR(userfield)=...)\n";
" Also see AppendCDRUserField().\n";
static char *setcdruserfield_app = "SetCDRUserField";
@@ -68,19 +67,21 @@ static char *appendcdruserfield_descrip =
" can use for data not stored anywhere else in the record.\n"
" CDR records can be used for billing or storing other arbitrary data\n"
" (I.E. telephone survey responses)\n"
" Also see SetCDRUserField().\n"
"\nThis application is deprecated in favor of Set(CDR(userfield)=...)\n";
" Also see SetCDRUserField().\n";
static char *appendcdruserfield_app = "AppendCDRUserField";
static char *appendcdruserfield_synopsis = "Append to the CDR user field";
STANDARD_LOCAL_USER;
static int action_setcdruserfield(struct mansession *s, const struct message *m)
LOCAL_USER_DECL;
static int action_setcdruserfield(struct mansession *s, struct message *m)
{
struct ast_channel *c = NULL;
const char *userfield = astman_get_header(m, "UserField");
const char *channel = astman_get_header(m, "Channel");
const char *append = astman_get_header(m, "Append");
char *userfield = astman_get_header(m, "UserField");
char *channel = astman_get_header(m, "Channel");
char *append = astman_get_header(m, "Append");
if (ast_strlen_zero(channel)) {
astman_send_error(s, m, "No Channel specified");
@@ -106,49 +107,37 @@ static int action_setcdruserfield(struct mansession *s, const struct message *m)
static int setcdruserfield_exec(struct ast_channel *chan, void *data)
{
struct ast_module_user *u;
struct localuser *u;
int res = 0;
static int dep_warning = 0;
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
if (chan->cdr && data) {
ast_cdr_setuserfield(chan, (char*)data);
}
if (!dep_warning) {
dep_warning = 1;
ast_log(LOG_WARNING, "SetCDRUserField is deprecated. Please use CDR(userfield) instead.\n");
}
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return res;
}
static int appendcdruserfield_exec(struct ast_channel *chan, void *data)
{
struct ast_module_user *u;
struct localuser *u;
int res = 0;
static int dep_warning = 0;
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
if (chan->cdr && data) {
ast_cdr_appenduserfield(chan, (char*)data);
}
if (!dep_warning) {
dep_warning = 1;
ast_log(LOG_WARNING, "AppendCDRUserField is deprecated. Please use CDR(userfield) instead.\n");
}
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
@@ -156,12 +145,12 @@ static int unload_module(void)
res |= ast_unregister_application(appendcdruserfield_app);
res |= ast_manager_unregister("SetCDRUserField");
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
int res;
@@ -172,4 +161,19 @@ static int load_module(void)
return res;
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "CDR user field apps");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

132
apps/app_setcidname.c Normal file
View File

@@ -0,0 +1,132 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2005, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief App to set callerid
*
* \ingroup applications
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/image.h"
#include "asterisk/callerid.h"
#include "asterisk/utils.h"
static char *tdesc = "Set CallerID Name";
static char *app = "SetCIDName";
static char *synopsis = "Set CallerID Name";
static char *descrip =
" SetCIDName(cname[|a]): Set Caller*ID Name on a call to a new\n"
"value, while preserving the original Caller*ID number. This is\n"
"useful for providing additional information to the called\n"
"party. \n"
"SetCIDName has been deprecated in favor of the function\n"
"CALLERID(name)\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int setcallerid_exec(struct ast_channel *chan, void *data)
{
char *tmp = NULL;
struct localuser *u;
char *opt;
static int deprecation_warning = 0;
if (!deprecation_warning) {
ast_log(LOG_WARNING, "SetCIDName is deprecated, please use Set(CALLERID(name)=value) instead.\n");
deprecation_warning = 1;
}
if (ast_strlen_zero(data)) {
ast_log(LOG_ERROR, "SetCIDName requires an argument!\n");
return 0;
}
LOCAL_USER_ADD(u);
tmp = ast_strdupa(data);
if (!tmp) {
ast_log(LOG_ERROR, "Out of memory\n");
LOCAL_USER_REMOVE(u);
return -1;
}
opt = strchr(tmp, '|');
if (opt) {
*opt = '\0';
}
ast_set_callerid(chan, NULL, tmp, NULL);
LOCAL_USER_REMOVE(u);
return 0;
}
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
int load_module(void)
{
return ast_register_application(app, setcallerid_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

131
apps/app_setcidnum.c Normal file
View File

@@ -0,0 +1,131 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2005, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
* Oliver Daudey <traveler@xs4all.nl>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief App to set callerid number
*
* \ingroup applications
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/image.h"
#include "asterisk/callerid.h"
#include "asterisk/utils.h"
static char *tdesc = "Set CallerID Number";
static char *app = "SetCIDNum";
static char *synopsis = "Set CallerID Number";
static char *descrip =
" SetCIDNum(cnum[|a]): Set Caller*ID Number on a call to a new\n"
"value, while preserving the original Caller*ID name. This is\n"
"useful for providing additional information to the called\n"
"party. Sets ANI as well if a flag is used.\n"
"SetCIDNum has been deprecated in favor of the function\n"
"CALLERID(number)\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int setcallerid_exec(struct ast_channel *chan, void *data)
{
int res = 0;
struct localuser *u;
char *opt;
int anitoo = 0;
char *tmp = NULL;
static int deprecation_warning = 0;
LOCAL_USER_ADD(u);
if (!deprecation_warning) {
ast_log(LOG_WARNING, "SetCIDNum is deprecated, please use Set(CALLERID(number)=value) instead.\n");
deprecation_warning = 1;
}
if (data)
tmp = ast_strdupa(data);
else
tmp = "";
opt = strchr(tmp, '|');
if (opt) {
*opt = '\0';
opt++;
if (*opt == 'a')
anitoo = 1;
}
ast_set_callerid(chan, tmp, NULL, anitoo ? tmp : NULL);
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
int load_module(void)
{
return ast_register_application(app, setcallerid_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

132
apps/app_setrdnis.c Normal file
View File

@@ -0,0 +1,132 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2005, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
* Oliver Daudey <traveler@xs4all.nl>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief App to set rdnis
*
* \ingroup applications
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/image.h"
#include "asterisk/callerid.h"
#include "asterisk/utils.h"
static char *tdesc = "Set RDNIS Number";
static char *app = "SetRDNIS";
static char *synopsis = "Set RDNIS Number";
static char *descrip =
" SetRDNIS(cnum): Set RDNIS Number on a call to a new\n"
"value.\n"
"SetRDNIS has been deprecated in favor of the function\n"
"CALLERID(rdnis)\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int setrdnis_exec(struct ast_channel *chan, void *data)
{
struct localuser *u;
char *opt, *n, *l;
char *tmp = NULL;
static int deprecation_warning = 0;
LOCAL_USER_ADD(u);
if (!deprecation_warning) {
ast_log(LOG_WARNING, "SetRDNIS is deprecated, please use Set(CALLERID(rdnis)=value) instead.\n");
deprecation_warning = 1;
}
if (data)
tmp = ast_strdupa(data);
else
tmp = "";
opt = strchr(tmp, '|');
if (opt)
*opt = '\0';
n = l = NULL;
ast_callerid_parse(tmp, &n, &l);
if (l) {
ast_shrink_phone_number(l);
ast_mutex_lock(&chan->lock);
if (chan->cid.cid_rdnis)
free(chan->cid.cid_rdnis);
chan->cid.cid_rdnis = (l[0]) ? strdup(l) : NULL;
ast_mutex_unlock(&chan->lock);
}
LOCAL_USER_REMOVE(u);
return 0;
}
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
int load_module(void)
{
return ast_register_application(app, setrdnis_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,19 +19,17 @@
/*! \file
*
* \brief App to set the ISDN Transfer Capability
*
* \author Frank Sautter - asterisk+at+sautter+dot+com
*
* \ingroup applications
*/
#include <string.h>
#include <stdlib.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <string.h>
#include <stdlib.h>
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
@@ -44,6 +42,9 @@ static char *app = "SetTransferCapability";
static char *synopsis = "Set ISDN Transfer Capability";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static struct { int val; char *name; } transcaps[] = {
{ AST_TRANS_CAP_SPEECH, "SPEECH" },
@@ -64,27 +65,20 @@ static char *descrip =
" RESTRICTED_DIGITAL : 0x09 - Restricted digital information\n"
" 3K1AUDIO : 0x10 - 3.1kHz Audio (fax calls)\n"
" DIGITAL_W_TONES : 0x11 - Unrestricted digital information with tones/announcements\n"
" VIDEO : 0x18 - Video\n"
" VIDEO : 0x18 - Video:\n"
"\n"
"This application is deprecated in favor of Set(CHANNEL(transfercapability)=...)\n"
;
static int settransfercapability_exec(struct ast_channel *chan, void *data)
{
char *tmp = NULL;
struct ast_module_user *u;
struct localuser *u;
int x;
char *opts;
int transfercapability = -1;
static int dep_warning = 0;
u = ast_module_user_add(chan);
if (!dep_warning) {
dep_warning = 1;
ast_log(LOG_WARNING, "SetTransferCapability is deprecated. Please use CHANNEL(transfercapability) instead.\n");
}
LOCAL_USER_ADD(u);
if (data)
tmp = ast_strdupa(data);
else
@@ -102,7 +96,7 @@ static int settransfercapability_exec(struct ast_channel *chan, void *data)
}
if (transfercapability < 0) {
ast_log(LOG_WARNING, "'%s' is not a valid transfer capability (see 'show application SetTransferCapability')\n", tmp);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return 0;
}
@@ -111,26 +105,41 @@ static int settransfercapability_exec(struct ast_channel *chan, void *data)
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Setting transfer capability to: 0x%.2x - %s.\n", transfercapability, tmp);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return 0;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, settransfercapability_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Set ISDN Transfer Capability");
char *description(void)
{
return synopsis;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,26 +19,20 @@
/*! \file
*
* \brief Skeleton application
*
* \author <Your Name Here> <<Your Email Here>>
*
* This is a skeleton for development of an Asterisk application
* This is a skeleton for development of an Asterisk application
* \ingroup applications
*/
/*** MODULEINFO
<defaultenabled>no</defaultenabled>
***/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
@@ -47,87 +41,109 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/app.h"
static char *tdesc = "Trivial skeleton Application";
static char *app = "Skel";
static char *synopsis =
"Skeleton application.";
static char *descrip = "This application is a template to build other applications from.\n"
" It shows you the basic structure to create your own Asterisk applications.\n";
enum {
OPTION_A = (1 << 0),
OPTION_B = (1 << 1),
OPTION_C = (1 << 2),
} option_flags;
#define OPTION_A (1 << 0) /* Option A */
#define OPTION_B (1 << 1) /* Option B(n) */
#define OPTION_C (1 << 2) /* Option C(str) */
#define OPTION_NULL (1 << 3) /* Dummy Termination */
enum {
OPTION_ARG_B = 0,
OPTION_ARG_C = 1,
/* This *must* be the last value in this enum! */
OPTION_ARG_ARRAY_SIZE = 2,
} option_args;
AST_APP_OPTIONS(app_opts,{
AST_APP_OPTION('a', OPTION_A),
AST_APP_OPTION_ARG('b', OPTION_B, OPTION_ARG_B),
AST_APP_OPTION_ARG('c', OPTION_C, OPTION_ARG_C),
AST_DECLARE_OPTIONS(app_opts,{
['a'] = { OPTION_A },
['b'] = { OPTION_B, 1 },
['c'] = { OPTION_C, 2 }
});
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int app_exec(struct ast_channel *chan, void *data)
{
int res = 0;
struct ast_flags flags;
struct ast_module_user *u;
char *parse, *opts[OPTION_ARG_ARRAY_SIZE];
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(dummy);
AST_APP_ARG(options);
);
struct localuser *u;
char *options=NULL;
char *dummy = NULL;
char *args;
int argc = 0;
char *opts[2];
char *argv[2];
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "%s requires an argument (dummy|[options])\n", app);
ast_log(LOG_WARNING, "%s requires an argument (dummy|[options])\n",app);
return -1;
}
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
/* Do our thing here */
/* We need to make a copy of the input string if we are going to modify it! */
parse = ast_strdupa(data);
args = ast_strdupa(data);
if (!args) {
ast_log(LOG_ERROR, "Out of memory!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
if ((argc = ast_app_separate_args(args, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
dummy = argv[0];
options = argv[1];
ast_parseoptions(app_opts, &flags, opts, options);
}
AST_STANDARD_APP_ARGS(args, parse);
if (args.argc == 2)
ast_app_parse_options(app_opts, &flags, opts, args.options);
if (!ast_strlen_zero(args.dummy))
ast_log(LOG_NOTICE, "Dummy value is : %s\n", args.dummy);
if (!ast_strlen_zero(dummy))
ast_log(LOG_NOTICE, "Dummy value is : %s\n", dummy);
if (ast_test_flag(&flags, OPTION_A))
ast_log(LOG_NOTICE, "Option A is set\n");
if (ast_test_flag(&flags, OPTION_B))
ast_log(LOG_NOTICE, "Option B is set with : %s\n", opts[OPTION_ARG_B] ? opts[OPTION_ARG_B] : "<unspecified>");
ast_log(LOG_NOTICE,"Option B is set with : %s\n", opts[0] ? opts[0] : "<unspecified>");
if (ast_test_flag(&flags, OPTION_C))
ast_log(LOG_NOTICE, "Option C is set with : %s\n", opts[OPTION_ARG_C] ? opts[OPTION_ARG_C] : "<unspecified>");
ast_module_user_remove(u);
ast_log(LOG_NOTICE,"Option C is set with : %s\n", opts[1] ? opts[1] : "<unspecified>");
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, app_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Skeleton (sample) Application");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -18,14 +18,9 @@
*
* \brief SMS application - ETSI ES 201 912 protocol 1 implimentation
* \ingroup applications
*
* \author Adrian Kennard
*
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -36,6 +31,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <sys/types.h>
#include <sys/stat.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
@@ -61,6 +60,8 @@ static volatile unsigned int seq; /* arbitrary message sequence number for
static char log_file[255];
static char spool_dir[255];
static char *tdesc = "SMS/PSTN handler";
static char *app = "SMS";
static char *synopsis = "Communicates with SMS service centres and SMS capable analogue phones";
@@ -93,6 +94,9 @@ static signed short wave[] = {
static unsigned char wavea[80];
#endif
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
/* SMS 7 bit character mapping to UCS-2 */
static const unsigned short defaultalphabet[] = {
@@ -193,7 +197,7 @@ static void sms_release (struct ast_channel *chan, void *data)
static void sms_messagetx (sms_t * h);
/*! \brief copy number, skipping non digits apart from leading + */
/*--- numcpy: copy number, skipping non digits apart from leading + */
static void numcpy (char *d, char *s)
{
if (*s == '+')
@@ -206,7 +210,7 @@ static void numcpy (char *d, char *s)
*d = 0;
}
/*! \brief static, return a date/time in ISO format */
/*--- isodate: static, return a date/time in ISO format */
static char * isodate (time_t t)
{
static char date[20];
@@ -214,7 +218,7 @@ static char * isodate (time_t t)
return date;
}
/*! \brief reads next UCS character from null terminated UTF-8 string and advanced pointer */
/*--- utf8decode: reads next UCS character from null terminated UTF-8 string and advanced pointer */
/* for non valid UTF-8 sequences, returns character as is */
/* Does not advance pointer for null termination */
static long utf8decode (unsigned char **pp)
@@ -260,7 +264,7 @@ static long utf8decode (unsigned char **pp)
return *p; /* not sensible */
}
/*! \brief takes a binary header (udhl bytes at udh) and UCS-2 message (udl characters at ud) and packs in to o using SMS 7 bit character codes */
/*--- packsms7: takes a binary header (udhl bytes at udh) and UCS-2 message (udl characters at ud) and packs in to o using SMS 7 bit character codes */
/* The return value is the number of septets packed in to o, which is internally limited to SMSLEN */
/* o can be null, in which case this is used to validate or count only */
/* if the input contains invalid characters then the return value is -1 */
@@ -330,7 +334,7 @@ static int packsms7 (unsigned char *o, int udhl, unsigned char *udh, int udl, un
return n;
}
/*! \brief takes a binary header (udhl bytes at udh) and UCS-2 message (udl characters at ud) and packs in to o using 8 bit character codes */
/*--- packsms8: takes a binary header (udhl bytes at udh) and UCS-2 message (udl characters at ud) and packs in to o using 8 bit character codes */
/* The return value is the number of bytes packed in to o, which is internally limited to 140 */
/* o can be null, in which case this is used to validate or count only */
/* if the input contains invalid characters then the return value is -1 */
@@ -362,7 +366,7 @@ static int packsms8 (unsigned char *o, int udhl, unsigned char *udh, int udl, un
return p;
}
/*! \brief takes a binary header (udhl bytes at udh) and UCS-2
/*--- packsms16: takes a binary header (udhl bytes at udh) and UCS-2
message (udl characters at ud) and packs in to o using 16 bit
UCS-2 character codes
The return value is the number of bytes packed in to o, which is
@@ -399,7 +403,7 @@ static int packsms16 (unsigned char *o, int udhl, unsigned char *udh, int udl, u
return p;
}
/*! \brief general pack, with length and data,
/*--- packsms: general pack, with length and data,
returns number of bytes of target used */
static int packsms (unsigned char dcs, unsigned char *base, unsigned int udhl, unsigned char *udh, int udl, unsigned short *ud)
{
@@ -431,7 +435,7 @@ static int packsms (unsigned char dcs, unsigned char *base, unsigned int udhl, u
}
/*! \brief pack a date and return */
/*--- packdate: pack a date and return */
static void packdate (unsigned char *o, time_t w)
{
struct tm *t = localtime (&w);
@@ -452,7 +456,7 @@ static void packdate (unsigned char *o, time_t w)
*o++ = ((z % 10) << 4) + z / 10;
}
/*! \brief unpack a date and return */
/*--- unpackdate: unpack a date and return */
static time_t unpackdate (unsigned char *i)
{
struct tm t;
@@ -467,10 +471,10 @@ static time_t unpackdate (unsigned char *i)
t.tm_min += 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
else
t.tm_min -= 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
return ast_mktime(&t, NULL);
return mktime (&t);
}
/*! \brief unpacks bytes (7 bit encoding) at i, len l septets,
/*--- unpacksms7: unpacks bytes (7 bit encoding) at i, len l septets,
and places in udh and ud setting udhl and udl. udh not used
if udhi not set */
static void unpacksms7 (unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
@@ -521,7 +525,7 @@ static void unpacksms7 (unsigned char *i, unsigned char l, unsigned char *udh, i
*udl = (o - ud);
}
/*! \brief unpacks bytes (8 bit encoding) at i, len l septets,
/*--- unpacksms8: unpacks bytes (8 bit encoding) at i, len l septets,
and places in udh and ud setting udhl and udl. udh not used
if udhi not set */
static void unpacksms8 (unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
@@ -546,7 +550,7 @@ static void unpacksms8 (unsigned char *i, unsigned char l, unsigned char *udh, i
*udl = (o - ud);
}
/*! \brief unpacks bytes (16 bit encoding) at i, len l septets,
/*--- unpacksms16: unpacks bytes (16 bit encoding) at i, len l septets,
and places in udh and ud setting udhl and udl.
udh not used if udhi not set */
static void unpacksms16 (unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
@@ -575,7 +579,7 @@ static void unpacksms16 (unsigned char *i, unsigned char l, unsigned char *udh,
*udl = (o - ud);
}
/*! \brief general unpack - starts with length byte (octet or septet) and returns number of bytes used, inc length */
/*--- unpacksms: general unpack - starts with length byte (octet or septet) and returns number of bytes used, inc length */
static int unpacksms (unsigned char dcs, unsigned char *i, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
{
int l = *i++;
@@ -589,7 +593,7 @@ static int unpacksms (unsigned char dcs, unsigned char *i, unsigned char *udh, i
return l + 1;
}
/*! \brief unpack an address from i, return byte length, unpack to o */
/*--- unpackaddress: unpack an address from i, return byte length, unpack to o */
static unsigned char unpackaddress (char *o, unsigned char *i)
{
unsigned char l = i[0],
@@ -606,7 +610,7 @@ static unsigned char unpackaddress (char *o, unsigned char *i)
return (l + 5) / 2;
}
/*! \brief store an address at o, and return number of bytes used */
/*--- packaddress: store an address at o, and return number of bytes used */
static unsigned char packaddress (unsigned char *o, char *i)
{
unsigned char p = 2;
@@ -631,7 +635,7 @@ static unsigned char packaddress (unsigned char *o, char *i)
return p;
}
/*! \brief Log the output, and remove file */
/*--- sms_log: Log the output, and remove file */
static void sms_log (sms_t * h, char status)
{
if (*h->oa || *h->da) {
@@ -662,16 +666,14 @@ static void sms_log (sms_t * h, char status)
*p++ = h->ud[n];
*p++ = '\n';
*p = 0;
if (write (o, line, strlen (line)) < 0) {
ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
}
write (o, line, strlen (line));
close (o);
}
*h->oa = *h->da = h->udl = 0;
}
}
/*! \brief parse and delete a file */
/*--- sms_readfile: parse and delete a file */
static void sms_readfile (sms_t * h, char *fn)
{
char line[1000];
@@ -692,8 +694,7 @@ static void sms_readfile (sms_t * h, char *fn)
}
while (fgets (line, sizeof (line), s))
{ /* process line in file */
char *p;
void *pp = &p;
unsigned char *p;
for (p = line; *p && *p != '\n' && *p != '\r'; p++);
*p = 0; /* strip eoln */
p = line;
@@ -713,7 +714,7 @@ static void sms_readfile (sms_t * h, char *fn)
{ /* parse message (UTF-8) */
unsigned char o = 0;
while (*p && o < SMSLEN)
h->ud[o++] = utf8decode(pp);
h->ud[o++] = utf8decode((unsigned char **)&p);
h->udl = o;
if (*p)
ast_log (LOG_WARNING, "UD too long in %s\n", fn);
@@ -757,7 +758,7 @@ static void sms_readfile (sms_t * h, char *fn)
t.tm_min = M;
t.tm_sec = S;
t.tm_isdst = -1;
h->scts = ast_mktime(&t, NULL);
h->scts = mktime (&t);
if (h->scts == (time_t) - 1)
ast_log (LOG_WARNING, "Bad date/timein %s: %s", fn, p);
}
@@ -854,7 +855,7 @@ static void sms_readfile (sms_t * h, char *fn)
}
}
/*! \brief white a received text message to a file */
/*--- sms_writefile: white a received text message to a file */
static void sms_writefile (sms_t * h)
{
char fn[200] = "", fn2[200] = "";
@@ -941,7 +942,7 @@ static void sms_writefile (sms_t * h)
}
}
/*! \brief read dir skipping dot files... */
/*--- readdirqueue: read dir skipping dot files... */
static struct dirent *readdirqueue (DIR * d, char *queue)
{
struct dirent *f;
@@ -951,7 +952,7 @@ static struct dirent *readdirqueue (DIR * d, char *queue)
return f;
}
/*! \brief handle the incoming message */
/*--- sms_handleincoming: handle the incoming message */
static unsigned char sms_handleincoming (sms_t * h)
{
unsigned char p = 3;
@@ -1022,7 +1023,8 @@ static unsigned char sms_handleincoming (sms_t * h)
#define NAME_MAX 1024
#endif
/*! \brief find and fill in next message, or send a REL if none waiting */
/*--- sms_nextoutgoing: find and fill in next message,
or send a REL if none waiting */
static void sms_nextoutgoing (sms_t * h)
{
char fn[100 + NAME_MAX] = "";
@@ -1048,7 +1050,7 @@ static void sms_nextoutgoing (sms_t * h)
unsigned char p = 2;
h->omsg[0] = 0x91; /* SMS_DATA */
if (h->smsc) { /* deliver */
h->omsg[p++] = (more ? 4 : 0) + ((h->udhl > 0) ? 0x40 : 0);
h->omsg[p++] = (more ? 4 : 0);
p += packaddress (h->omsg + p, h->oa);
h->omsg[p++] = h->pid;
h->omsg[p++] = h->dcs;
@@ -1176,31 +1178,33 @@ static void sms_messagetx(sms_t * h)
static int sms_generate (struct ast_channel *chan, void *data, int len, int samples)
{
struct ast_frame f = { 0 };
#define MAXSAMPLES (800)
unsigned char waste[AST_FRIENDLY_OFFSET];
#ifdef OUTALAW
unsigned char *buf;
unsigned char buf[800];
#else
short *buf;
signed short buf[800];
#endif
#define SAMPLE2LEN sizeof(*buf)
sms_t *h = data;
int i;
if (samples > MAXSAMPLES) {
ast_log (LOG_WARNING, "Only doing %d samples (%d requested)\n",
MAXSAMPLES, samples);
samples = MAXSAMPLES;
if (len > sizeof (buf)) {
ast_log (LOG_WARNING, "Only doing %d bytes (%d bytes requested)\n", (int)(sizeof (buf) / sizeof (signed short)), len);
len = sizeof (buf);
#ifdef OUTALAW
samples = len;
#else
samples = len / 2;
#endif
}
len = samples * SAMPLE2LEN + AST_FRIENDLY_OFFSET;
buf = alloca(len);
waste[0] = 0; /* make compiler happy */
f.frametype = AST_FRAME_VOICE;
#ifdef OUTALAW
f.subclass = AST_FORMAT_ALAW;
f.datalen = samples;
#else
f.subclass = AST_FORMAT_SLINEAR;
f.datalen = samples * 2;
#endif
f.datalen = samples * SAMPLE2LEN;
f.offset = AST_FRIENDLY_OFFSET;
f.mallocd = 0;
f.data = buf;
@@ -1252,8 +1256,6 @@ static int sms_generate (struct ast_channel *chan, void *data, int len, int samp
return -1;
}
return 0;
#undef SAMPLE2LEN
#undef MAXSAMPLES
}
static void sms_process (sms_t * h, int samples, signed short *data)
@@ -1359,17 +1361,17 @@ static struct ast_generator smsgen = {
static int sms_exec (struct ast_channel *chan, void *data)
{
int res = -1;
struct ast_module_user *u;
struct localuser *u;
struct ast_frame *f;
sms_t h = { 0 };
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
h.ipc0 = h.ipc1 = 20; /* phase for cosine */
h.dcs = 0xF1; /* default */
if (!data) {
ast_log (LOG_ERROR, "Requires queue name at least\n");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
@@ -1382,20 +1384,20 @@ static int sms_exec (struct ast_channel *chan, void *data)
answer = 0;
if (!*d || *d == '|') {
ast_log (LOG_ERROR, "Requires queue name\n");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
for (p = d; *p && *p != '|'; p++);
if (p - d >= sizeof (h.queue)) {
ast_log (LOG_ERROR, "Queue name too long\n");
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return -1;
}
strncpy(h.queue, (char *)d, p - d);
strncpy (h.queue, d, p - d);
if (*p == '|')
p++;
d = p;
for (p = (unsigned char *)h.queue; *p; p++)
for (p = h.queue; *p; p++)
if (!isalnum (*p))
*p = '-'; /* make very safe for filenames */
while (*d && *d != '|') {
@@ -1427,20 +1429,20 @@ static int sms_exec (struct ast_channel *chan, void *data)
}
if (*d == '|') {
/* submitting a message, not taking call. */
/* deprecated, use smsq instead */
/* depricated, use smsq instead */
d++;
h.scts = time (0);
for (p = d; *p && *p != '|'; p++);
if (*p)
*p++ = 0;
if (strlen ((char *)d) >= sizeof (h.oa)) {
if (strlen (d) >= sizeof (h.oa)) {
ast_log (LOG_ERROR, "Address too long %s\n", d);
return 0;
}
if (h.smsc) {
ast_copy_string (h.oa, (char *)d, sizeof (h.oa));
ast_copy_string (h.oa, d, sizeof (h.oa));
} else {
ast_copy_string (h.da, (char *)d, sizeof (h.da));
ast_copy_string (h.da, d, sizeof (h.da));
}
if (!h.smsc)
ast_copy_string (h.oa, h.cli, sizeof (h.oa));
@@ -1457,7 +1459,7 @@ static int sms_exec (struct ast_channel *chan, void *data)
h.rx = 0; /* sent message */
h.mr = -1;
sms_writefile (&h);
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return 0;
}
@@ -1481,13 +1483,13 @@ static int sms_exec (struct ast_channel *chan, void *data)
res = ast_set_read_format (chan, AST_FORMAT_SLINEAR);
if (res < 0) {
ast_log (LOG_ERROR, "Unable to set to linear mode, giving up\n");
ast_module_user_remove(u);
LOCAL_USER_REMOVE (u);
return -1;
}
if (ast_activate_generator (chan, &smsgen, &h) < 0) {
ast_log (LOG_ERROR, "Failed to activate generator on '%s'\n", chan->name);
ast_module_user_remove(u);
LOCAL_USER_REMOVE (u);
return -1;
}
@@ -1506,22 +1508,22 @@ static int sms_exec (struct ast_channel *chan, void *data)
sms_log (&h, '?'); /* log incomplete message */
ast_module_user_remove(u);
LOCAL_USER_REMOVE (u);
return (h.err);
}
static int unload_module(void)
int unload_module (void)
{
int res;
res = ast_unregister_application (app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module (void)
{
#ifdef OUTALAW
{
@@ -1535,4 +1537,19 @@ static int load_module(void)
return ast_register_application (app, sms_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "SMS/PSTN handler");
char *description (void)
{
return tdesc;
}
int usecount (void)
{
int res;
STANDARD_USECOUNT (res);
return res;
}
char *key ()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,22 +19,20 @@
/*! \file
*
* \brief SoftHangup application
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
@@ -44,6 +42,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
static char *synopsis = "Soft Hangup Application";
static char *tdesc = "Hangs up the requested channel";
static char *desc = " SoftHangup(Technology/resource|options)\n"
"Hangs up the requested channel. If there are no channels to hangup,\n"
"the application will report it.\n"
@@ -52,10 +52,13 @@ static char *desc = " SoftHangup(Technology/resource|options)\n"
static char *app = "SoftHangup";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int softhangup_exec(struct ast_channel *chan, void *data)
{
struct ast_module_user *u;
struct localuser *u;
struct ast_channel *c=NULL;
char *options, *cut, *cdata, *match;
char name[AST_CHANNEL_NAME] = "";
@@ -66,7 +69,7 @@ static int softhangup_exec(struct ast_channel *chan, void *data)
return 0;
}
u = ast_module_user_add(chan);
LOCAL_USER_ADD(u);
cdata = ast_strdupa(data);
match = strsep(&cdata, "|");
@@ -74,12 +77,12 @@ static int softhangup_exec(struct ast_channel *chan, void *data)
all = options && strchr(options,'a');
c = ast_channel_walk_locked(NULL);
while (c) {
ast_copy_string(name, c->name, sizeof(name));
strncpy(name, c->name, sizeof(name)-1);
ast_mutex_unlock(&c->lock);
/* XXX watch out, i think it is wrong to access c-> after unlocking! */
if (all) {
/* CAPI is set up like CAPI[foo/bar]/clcnt */
if (!strcmp(c->tech->type, "CAPI"))
if (!strcmp(c->type,"CAPI"))
cut = strrchr(name,'/');
/* Basically everything else is Foo/Bar-Z */
else
@@ -97,25 +100,40 @@ static int softhangup_exec(struct ast_channel *chan, void *data)
c = ast_channel_walk_locked(c);
}
ast_module_user_remove(u);
LOCAL_USER_REMOVE(u);
return 0;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
ast_module_user_hangup_all();
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, softhangup_exec, synopsis, desc);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Hangs up the requested channel");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

Some files were not shown because too many files have changed in this diff Show More