mirror of
				https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw.git
				synced 2025-11-04 05:53:26 +00:00 
			
		
		
		
	Compare commits
	
		
			588 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					46ab31c377 | ||
| 
						 | 
					6c87ac9af3 | ||
| 
						 | 
					23c623b487 | ||
| 
						 | 
					1a099fd34c | ||
| 
						 | 
					58dc88bc31 | ||
| 
						 | 
					aac84edc9d | ||
| 
						 | 
					172f5acfce | ||
| 
						 | 
					fdbefde869 | ||
| 
						 | 
					25ecc91c3b | ||
| 
						 | 
					995529548b | ||
| 
						 | 
					0c04500ac5 | ||
| 
						 | 
					a0b69f1896 | ||
| 
						 | 
					fbf78d13f1 | ||
| 
						 | 
					df9192efee | ||
| 
						 | 
					70a658a2ba | ||
| 
						 | 
					2764bdb1aa | ||
| 
						 | 
					55fdfc223e | ||
| 
						 | 
					8f33303660 | ||
| 
						 | 
					a94c56e4c6 | ||
| 
						 | 
					2ebcf5c34a | ||
| 
						 | 
					f936e10f07 | ||
| 
						 | 
					e303fa9ff3 | ||
| 
						 | 
					958f5e74cc | ||
| 
						 | 
					1e8d5fa44b | ||
| 
						 | 
					374ad788d8 | ||
| 
						 | 
					da07b90f0f | ||
| 
						 | 
					fa495d669f | ||
| 
						 | 
					439c86fc58 | ||
| 
						 | 
					74e83d3d82 | ||
| 
						 | 
					d55be05af1 | ||
| 
						 | 
					8f91a7f450 | ||
| 
						 | 
					da3a5759e1 | ||
| 
						 | 
					29e671f257 | ||
| 
						 | 
					d6a7e17911 | ||
| 
						 | 
					3f4a4cb49c | ||
| 
						 | 
					3d2b76fd95 | ||
| 
						 | 
					276a414aa3 | ||
| 
						 | 
					c534ad17dc | ||
| 
						 | 
					3f2c15f275 | ||
| 
						 | 
					38533ba9b3 | ||
| 
						 | 
					39889e4389 | ||
| 
						 | 
					c824fe4eb0 | ||
| 
						 | 
					124a3e0b34 | ||
| 
						 | 
					96c6e06681 | ||
| 
						 | 
					ce18705875 | ||
| 
						 | 
					41ab87f67c | ||
| 
						 | 
					a8739fc7be | ||
| 
						 | 
					21dfeff8aa | ||
| 
						 | 
					f486e741a4 | ||
| 
						 | 
					268568593e | ||
| 
						 | 
					41d59205c0 | ||
| 
						 | 
					036612b035 | ||
| 
						 | 
					6bad138c96 | ||
| 
						 | 
					8dc3597085 | ||
| 
						 | 
					d70eef6421 | ||
| 
						 | 
					33d97f721d | ||
| 
						 | 
					d57310731f | ||
| 
						 | 
					a8c684b51f | ||
| 
						 | 
					03fcc91aad | ||
| 
						 | 
					9de30e7cc4 | ||
| 
						 | 
					d64c041cdb | ||
| 
						 | 
					d02716d6c2 | ||
| 
						 | 
					a065e632c0 | ||
| 
						 | 
					bd060c3c99 | ||
| 
						 | 
					97cae477fb | ||
| 
						 | 
					02c880a7dd | ||
| 
						 | 
					ba09687768 | ||
| 
						 | 
					a4b677c45a | ||
| 
						 | 
					6b7afe8f57 | ||
| 
						 | 
					4131a65c4d | ||
| 
						 | 
					6a5e5ac2d4 | ||
| 
						 | 
					b066bd0c86 | ||
| 
						 | 
					d6769ea207 | ||
| 
						 | 
					ca280a1a84 | ||
| 
						 | 
					a24dcc61d7 | ||
| 
						 | 
					62d9df684f | ||
| 
						 | 
					8358c4ba07 | ||
| 
						 | 
					4c77e9b748 | ||
| 
						 | 
					33347a4f5d | ||
| 
						 | 
					7d86d4c523 | ||
| 
						 | 
					eb984bd630 | ||
| 
						 | 
					b3d14eb552 | ||
| 
						 | 
					907744e2fc | ||
| 
						 | 
					776846a0b9 | ||
| 
						 | 
					59e7cf4437 | ||
| 
						 | 
					b2064423fe | ||
| 
						 | 
					97a9312be8 | ||
| 
						 | 
					427cede4ba | ||
| 
						 | 
					7371663aeb | ||
| 
						 | 
					fe53edd776 | ||
| 
						 | 
					4f6a7ad5f8 | ||
| 
						 | 
					55a9229922 | ||
| 
						 | 
					7802ccc8d6 | ||
| 
						 | 
					3ff5151661 | ||
| 
						 | 
					5936a9c23e | ||
| 
						 | 
					9ffaba7c1b | ||
| 
						 | 
					535ede2598 | ||
| 
						 | 
					6ccdaa243f | ||
| 
						 | 
					ace0b946ff | ||
| 
						 | 
					a34036c296 | ||
| 
						 | 
					9fec391d6e | ||
| 
						 | 
					a835fa85d7 | ||
| 
						 | 
					2c66c15227 | ||
| 
						 | 
					92a73cd637 | ||
| 
						 | 
					6e2795bfbf | ||
| 
						 | 
					276b595361 | ||
| 
						 | 
					3c293b418b | ||
| 
						 | 
					41425e9b85 | ||
| 
						 | 
					31682a3274 | ||
| 
						 | 
					870f94b493 | ||
| 
						 | 
					242e9ada91 | ||
| 
						 | 
					9b444fd417 | ||
| 
						 | 
					e9473f610e | ||
| 
						 | 
					53002b3a00 | ||
| 
						 | 
					a098b65252 | ||
| 
						 | 
					78b0055e5e | ||
| 
						 | 
					648bec3982 | ||
| 
						 | 
					c2a8f59560 | ||
| 
						 | 
					38404969df | ||
| 
						 | 
					19c430feba | ||
| 
						 | 
					3ba409558e | ||
| 
						 | 
					60be627557 | ||
| 
						 | 
					8cfe7df3f1 | ||
| 
						 | 
					ba94b6d7be | ||
| 
						 | 
					30e01355f6 | ||
| 
						 | 
					06624e13d4 | ||
| 
						 | 
					19539866e5 | ||
| 
						 | 
					1dc2dcebbf | ||
| 
						 | 
					6049a63d1d | ||
| 
						 | 
					3ef8e76534 | ||
| 
						 | 
					fbf07f3f69 | ||
| 
						 | 
					de133113a0 | ||
| 
						 | 
					6d0a59a1bf | ||
| 
						 | 
					2491401932 | ||
| 
						 | 
					fbbe8f2f98 | ||
| 
						 | 
					71d42e778a | ||
| 
						 | 
					8a2a1b22fe | ||
| 
						 | 
					a790f0c082 | ||
| 
						 | 
					0ab152b2c6 | ||
| 
						 | 
					2741d6bb0e | ||
| 
						 | 
					74d0e5c318 | ||
| 
						 | 
					c4ef4a21c6 | ||
| 
						 | 
					ee2f33bf9a | ||
| 
						 | 
					531470a0ca | ||
| 
						 | 
					9dc73593a3 | ||
| 
						 | 
					ae6858bddf | ||
| 
						 | 
					99d4d368e8 | ||
| 
						 | 
					8667d5169d | ||
| 
						 | 
					1add5a53cb | ||
| 
						 | 
					729bf3e45a | ||
| 
						 | 
					2f34b53b5b | ||
| 
						 | 
					ad79f9eb99 | ||
| 
						 | 
					9e494e67c7 | ||
| 
						 | 
					5322473d04 | ||
| 
						 | 
					c57ad7ff9a | ||
| 
						 | 
					c59b5c533d | ||
| 
						 | 
					0653cc8a7c | ||
| 
						 | 
					246233d0d4 | ||
| 
						 | 
					a910a81b7c | ||
| 
						 | 
					c8acee2234 | ||
| 
						 | 
					55863e42c1 | ||
| 
						 | 
					6177cae2a2 | ||
| 
						 | 
					6af3ccf65d | ||
| 
						 | 
					03cb5f3397 | ||
| 
						 | 
					113141d4f9 | ||
| 
						 | 
					993ea6be7a | ||
| 
						 | 
					889fe7f203 | ||
| 
						 | 
					efd09d0b77 | ||
| 
						 | 
					ffbc618a13 | ||
| 
						 | 
					563ffc51b5 | ||
| 
						 | 
					51b42ff2e1 | ||
| 
						 | 
					7a755be4c2 | ||
| 
						 | 
					06ea49159e | ||
| 
						 | 
					869b21c869 | ||
| 
						 | 
					37a808c5a5 | ||
| 
						 | 
					24b8c0ce92 | ||
| 
						 | 
					fe67e094ad | ||
| 
						 | 
					fbcf39976e | ||
| 
						 | 
					4863591c23 | ||
| 
						 | 
					827da2c867 | ||
| 
						 | 
					efe1571b7b | ||
| 
						 | 
					6521fc0695 | ||
| 
						 | 
					f5531845bc | ||
| 
						 | 
					13fae78b32 | ||
| 
						 | 
					b7d395d83a | ||
| 
						 | 
					6fbbeec064 | ||
| 
						 | 
					0ffa3bdc45 | ||
| 
						 | 
					ca8639dc05 | ||
| 
						 | 
					8d6a193c1a | ||
| 
						 | 
					58a1ba85c7 | ||
| 
						 | 
					b0c05aa3a9 | ||
| 
						 | 
					0996a1e4ae | ||
| 
						 | 
					7e9ddc9904 | ||
| 
						 | 
					04bbb9de3e | ||
| 
						 | 
					bea56788cb | ||
| 
						 | 
					48bcc2ee12 | ||
| 
						 | 
					080935a8c7 | ||
| 
						 | 
					a466f57007 | ||
| 
						 | 
					41f77d8018 | ||
| 
						 | 
					e674345e29 | ||
| 
						 | 
					3f8139c55f | ||
| 
						 | 
					98c09b3f30 | ||
| 
						 | 
					7462b95829 | ||
| 
						 | 
					7a64182f9a | ||
| 
						 | 
					d19de2ee80 | ||
| 
						 | 
					08eb9352ab | ||
| 
						 | 
					0b79d21c7f | ||
| 
						 | 
					bce5f29265 | ||
| 
						 | 
					3d5a2dd19f | ||
| 
						 | 
					7f90ddb519 | ||
| 
						 | 
					c66ab2c4c3 | ||
| 
						 | 
					f53796c1fe | ||
| 
						 | 
					14b27a8893 | ||
| 
						 | 
					21be42abed | ||
| 
						 | 
					2d681fd84c | ||
| 
						 | 
					c39b1bffec | ||
| 
						 | 
					62612e8575 | ||
| 
						 | 
					af932ce3bc | ||
| 
						 | 
					265b0a8045 | ||
| 
						 | 
					74390c521e | ||
| 
						 | 
					abfb858f0c | ||
| 
						 | 
					6500d72aaf | ||
| 
						 | 
					d6877eb8f9 | ||
| 
						 | 
					ebb9bf3f12 | ||
| 
						 | 
					61cf9bb5f1 | ||
| 
						 | 
					a7152e055a | ||
| 
						 | 
					63866009e2 | ||
| 
						 | 
					dab89af070 | ||
| 
						 | 
					eebbf2b1fc | ||
| 
						 | 
					e885bc5c24 | ||
| 
						 | 
					173dc129fc | ||
| 
						 | 
					3abced8d64 | ||
| 
						 | 
					a48ff4a738 | ||
| 
						 | 
					6c92f9d83e | ||
| 
						 | 
					9852e22101 | ||
| 
						 | 
					b141cccbfb | ||
| 
						 | 
					ec45068972 | ||
| 
						 | 
					832bcdf631 | ||
| 
						 | 
					73f9c02f49 | ||
| 
						 | 
					6a25a61142 | ||
| 
						 | 
					1dbbed169a | ||
| 
						 | 
					a8f27abe12 | ||
| 
						 | 
					ca2aec0235 | ||
| 
						 | 
					e827831514 | ||
| 
						 | 
					923d60bb12 | ||
| 
						 | 
					f2bf8dc8c8 | ||
| 
						 | 
					055ded74de | ||
| 
						 | 
					3ff71284fa | ||
| 
						 | 
					cc0b97e197 | ||
| 
						 | 
					8c69e29820 | ||
| 
						 | 
					843d9038ce | ||
| 
						 | 
					d071a30238 | ||
| 
						 | 
					3ab8ca4d84 | ||
| 
						 | 
					23f4048b57 | ||
| 
						 | 
					401b740ccd | ||
| 
						 | 
					a468b0f57f | ||
| 
						 | 
					b0cfa7272e | ||
| 
						 | 
					683e05f60b | ||
| 
						 | 
					16b637bf1b | ||
| 
						 | 
					2698540c1e | ||
| 
						 | 
					d2f5e69d3e | ||
| 
						 | 
					ce64f18587 | ||
| 
						 | 
					667fa59b0c | ||
| 
						 | 
					5a6220f43b | ||
| 
						 | 
					7c6dd3c2c3 | ||
| 
						 | 
					740af6ed44 | ||
| 
						 | 
					782d607962 | ||
| 
						 | 
					50e52e45f9 | ||
| 
						 | 
					a2d10216ea | ||
| 
						 | 
					f54eb96338 | ||
| 
						 | 
					a2b1c5e6f6 | ||
| 
						 | 
					c5c1430a1c | ||
| 
						 | 
					f7de9aea7b | ||
| 
						 | 
					199c5e965e | ||
| 
						 | 
					06a49fc04b | ||
| 
						 | 
					6349bd422a | ||
| 
						 | 
					796a4a1325 | ||
| 
						 | 
					2cf6652ba2 | ||
| 
						 | 
					9b508f6b53 | ||
| 
						 | 
					6e26c70f46 | ||
| 
						 | 
					9a34592c09 | ||
| 
						 | 
					7eb6f2cb56 | ||
| 
						 | 
					83fd8a5692 | ||
| 
						 | 
					17058484d1 | ||
| 
						 | 
					166077ea48 | ||
| 
						 | 
					0c6c3c1da6 | ||
| 
						 | 
					fe9a1fe03b | ||
| 
						 | 
					1e4a34d45e | ||
| 
						 | 
					189f29e939 | ||
| 
						 | 
					d2ce444008 | ||
| 
						 | 
					ef9420adf5 | ||
| 
						 | 
					cb96e05a91 | ||
| 
						 | 
					f6387dc766 | ||
| 
						 | 
					1b1d7ed98f | ||
| 
						 | 
					df7d97e4b4 | ||
| 
						 | 
					85978dadab | ||
| 
						 | 
					9aaaab6b3b | ||
| 
						 | 
					c1ad553d86 | ||
| 
						 | 
					c1bf4694e7 | ||
| 
						 | 
					1442c5a99e | ||
| 
						 | 
					dac2ca7e21 | ||
| 
						 | 
					375252279c | ||
| 
						 | 
					295570c631 | ||
| 
						 | 
					a93c6e9263 | ||
| 
						 | 
					30907dc9d8 | ||
| 
						 | 
					14f8a08f44 | ||
| 
						 | 
					c63f15a9a7 | ||
| 
						 | 
					ca538fc5eb | ||
| 
						 | 
					6be2c49538 | ||
| 
						 | 
					91088c305f | ||
| 
						 | 
					900cd6518a | ||
| 
						 | 
					fa810e8ccd | ||
| 
						 | 
					497611ae84 | ||
| 
						 | 
					2b89617aad | ||
| 
						 | 
					b542b0457b | ||
| 
						 | 
					120568651a | ||
| 
						 | 
					f1d301a9a6 | ||
| 
						 | 
					c9a6280c94 | ||
| 
						 | 
					b5583cde41 | ||
| 
						 | 
					6c1cd63a57 | ||
| 
						 | 
					0d7ba56f5c | ||
| 
						 | 
					3ac604e3ad | ||
| 
						 | 
					9fb8ddf00e | ||
| 
						 | 
					182ca3bad4 | ||
| 
						 | 
					f027f17dcb | ||
| 
						 | 
					ac772d8b0c | ||
| 
						 | 
					9d9f44ac71 | ||
| 
						 | 
					84274e4e9b | ||
| 
						 | 
					c5479fe086 | ||
| 
						 | 
					538d2c53d9 | ||
| 
						 | 
					8de58e79b8 | ||
| 
						 | 
					5e8d7995d1 | ||
| 
						 | 
					3239f6212e | ||
| 
						 | 
					209eb9f103 | ||
| 
						 | 
					ef6304e4a1 | ||
| 
						 | 
					21cdbfc196 | ||
| 
						 | 
					fc8067348b | ||
| 
						 | 
					9f11dc5616 | ||
| 
						 | 
					ca0818c760 | ||
| 
						 | 
					c12bfb7ffc | ||
| 
						 | 
					228e591589 | ||
| 
						 | 
					58128258b0 | ||
| 
						 | 
					e7ae69a7be | ||
| 
						 | 
					7e37ce6008 | ||
| 
						 | 
					dbe09dd515 | ||
| 
						 | 
					217d31d62f | ||
| 
						 | 
					47642f245d | ||
| 
						 | 
					cb760bdebe | ||
| 
						 | 
					e3f8bca424 | ||
| 
						 | 
					9fc8a02196 | ||
| 
						 | 
					e36b775eae | ||
| 
						 | 
					622dd61764 | ||
| 
						 | 
					e81c1176aa | ||
| 
						 | 
					ed0c1aa9d5 | ||
| 
						 | 
					ac69ea9cdf | ||
| 
						 | 
					0a40379214 | ||
| 
						 | 
					72bc8da537 | ||
| 
						 | 
					c3132fd508 | ||
| 
						 | 
					96c3107daf | ||
| 
						 | 
					ad21a0e166 | ||
| 
						 | 
					32d15cc8ba | ||
| 
						 | 
					1fd50e5306 | ||
| 
						 | 
					6802374574 | ||
| 
						 | 
					82c1d1eb20 | ||
| 
						 | 
					5a5169e15c | ||
| 
						 | 
					7c0b70a94e | ||
| 
						 | 
					ca6a8495e1 | ||
| 
						 | 
					c0a2196f91 | ||
| 
						 | 
					da026abc27 | ||
| 
						 | 
					27780313ac | ||
| 
						 | 
					e5ed946bdb | ||
| 
						 | 
					c319b79baa | ||
| 
						 | 
					2818db8b33 | ||
| 
						 | 
					0415de74b8 | ||
| 
						 | 
					4075b8805d | ||
| 
						 | 
					8ab3fbbaf2 | ||
| 
						 | 
					cc39218dce | ||
| 
						 | 
					8dbc9ed408 | ||
| 
						 | 
					ba25eab0fa | ||
| 
						 | 
					aa823bf24b | ||
| 
						 | 
					a714abfc91 | ||
| 
						 | 
					9270e91c09 | ||
| 
						 | 
					b7974e2fa4 | ||
| 
						 | 
					1e174875bf | ||
| 
						 | 
					c26b665c0c | ||
| 
						 | 
					0479b2a15f | ||
| 
						 | 
					ff6606cacb | ||
| 
						 | 
					407b1f186d | ||
| 
						 | 
					de2a4d7c22 | ||
| 
						 | 
					48aff62341 | ||
| 
						 | 
					852ba86949 | ||
| 
						 | 
					662fa421c6 | ||
| 
						 | 
					d14163e74f | ||
| 
						 | 
					11b4810142 | ||
| 
						 | 
					9ecceb651b | ||
| 
						 | 
					426a9d9103 | ||
| 
						 | 
					17bf603222 | ||
| 
						 | 
					bcd52e5724 | ||
| 
						 | 
					956242dcec | ||
| 
						 | 
					e686675f7d | ||
| 
						 | 
					4ca0b0d1fa | ||
| 
						 | 
					efd645e5a8 | ||
| 
						 | 
					f0504e86b3 | ||
| 
						 | 
					e28b673fba | ||
| 
						 | 
					a77eade744 | ||
| 
						 | 
					6531726a02 | ||
| 
						 | 
					31b4729f27 | ||
| 
						 | 
					a729db62a9 | ||
| 
						 | 
					5336f57f05 | ||
| 
						 | 
					eb72ff058f | ||
| 
						 | 
					8a91d2c04e | ||
| 
						 | 
					55e0dcf254 | ||
| 
						 | 
					23e7bf1c00 | ||
| 
						 | 
					10d487e13f | ||
| 
						 | 
					40f5033cf9 | ||
| 
						 | 
					b1bb1fa187 | ||
| 
						 | 
					1d121483f6 | ||
| 
						 | 
					124441af1f | ||
| 
						 | 
					b861db97ea | ||
| 
						 | 
					08e07046f9 | ||
| 
						 | 
					a5e0cf09a6 | ||
| 
						 | 
					f2388eab71 | ||
| 
						 | 
					120865833c | ||
| 
						 | 
					e6d8e91b3a | ||
| 
						 | 
					475f868b7f | ||
| 
						 | 
					0063ca2fb0 | ||
| 
						 | 
					610fda6108 | ||
| 
						 | 
					352eed09ae | ||
| 
						 | 
					0a89e92a5e | ||
| 
						 | 
					dde80f3f61 | ||
| 
						 | 
					9a7ccc3746 | ||
| 
						 | 
					910189d0a1 | ||
| 
						 | 
					8482e8374c | ||
| 
						 | 
					fee4fa9492 | ||
| 
						 | 
					4dba769577 | ||
| 
						 | 
					da895b1151 | ||
| 
						 | 
					a74c0ea2db | ||
| 
						 | 
					6a26c16eb0 | ||
| 
						 | 
					af8e00ffe8 | ||
| 
						 | 
					6931f9a7a4 | ||
| 
						 | 
					544448abea | ||
| 
						 | 
					e547bdd1ce | ||
| 
						 | 
					d1562a7766 | ||
| 
						 | 
					304b3eb328 | ||
| 
						 | 
					9cd5233609 | ||
| 
						 | 
					35a382968c | ||
| 
						 | 
					7066af825a | ||
| 
						 | 
					acc10353fe | ||
| 
						 | 
					bca0ef6cd9 | ||
| 
						 | 
					cede2a4b7c | ||
| 
						 | 
					337209a6ea | ||
| 
						 | 
					56e0443e1c | ||
| 
						 | 
					b1a1b4000e | ||
| 
						 | 
					8838c62fe9 | ||
| 
						 | 
					704c4f0adf | ||
| 
						 | 
					bc0346e080 | ||
| 
						 | 
					5928dc9345 | ||
| 
						 | 
					04da5e5e98 | ||
| 
						 | 
					54b4f82f91 | ||
| 
						 | 
					3d7b58d77a | ||
| 
						 | 
					604410cd13 | ||
| 
						 | 
					b340f90c9e | ||
| 
						 | 
					3c8ccb6724 | ||
| 
						 | 
					d4e6aa42ca | ||
| 
						 | 
					e6df0e47e7 | ||
| 
						 | 
					54eb0e1204 | ||
| 
						 | 
					b38fb8911f | ||
| 
						 | 
					1b3a385b9d | ||
| 
						 | 
					dbd70c7b68 | ||
| 
						 | 
					a19547b7a1 | ||
| 
						 | 
					06823731d8 | ||
| 
						 | 
					ed1cff5ab9 | ||
| 
						 | 
					f2321b7a72 | ||
| 
						 | 
					4219904cb2 | ||
| 
						 | 
					b2753f2044 | ||
| 
						 | 
					ba61f68137 | ||
| 
						 | 
					9e1d164469 | ||
| 
						 | 
					0ec1d4e17c | ||
| 
						 | 
					d761d355f9 | ||
| 
						 | 
					8d064dfd24 | ||
| 
						 | 
					7181cc1f02 | ||
| 
						 | 
					60f8e31a2f | ||
| 
						 | 
					086c3f3c67 | ||
| 
						 | 
					d0b470d1a9 | ||
| 
						 | 
					77f76d0be5 | ||
| 
						 | 
					892dec0be9 | ||
| 
						 | 
					c430d19112 | ||
| 
						 | 
					7b8e419d92 | ||
| 
						 | 
					4f7613eeb1 | ||
| 
						 | 
					01f039538e | ||
| 
						 | 
					d2e3a52230 | ||
| 
						 | 
					2924825bc6 | ||
| 
						 | 
					bd86f94a09 | ||
| 
						 | 
					1083533db4 | ||
| 
						 | 
					0793d2f5d5 | ||
| 
						 | 
					a8c6a9c37a | ||
| 
						 | 
					2da99a2946 | ||
| 
						 | 
					c3eed40f00 | ||
| 
						 | 
					515e341ff6 | ||
| 
						 | 
					8bda7a7766 | ||
| 
						 | 
					df5d219f39 | ||
| 
						 | 
					5656fbf49d | ||
| 
						 | 
					19d640e806 | ||
| 
						 | 
					207ab51270 | ||
| 
						 | 
					c3cc654add | ||
| 
						 | 
					b911b879d8 | ||
| 
						 | 
					af07f66ca3 | ||
| 
						 | 
					dd0c522cd4 | ||
| 
						 | 
					37d11c80da | ||
| 
						 | 
					1355d7e4f7 | ||
| 
						 | 
					fdd603c4c8 | ||
| 
						 | 
					1fc6999a77 | ||
| 
						 | 
					220f487238 | ||
| 
						 | 
					edc00f4ea7 | ||
| 
						 | 
					a49e32a1ab | ||
| 
						 | 
					dd4ede34ad | ||
| 
						 | 
					3aa815755d | ||
| 
						 | 
					3261dc7540 | ||
| 
						 | 
					771b26a043 | ||
| 
						 | 
					36a81129ec | ||
| 
						 | 
					a390d0ba52 | ||
| 
						 | 
					b759473d10 | ||
| 
						 | 
					c3cfae2cf8 | ||
| 
						 | 
					3cbfb8a53c | ||
| 
						 | 
					275ac97036 | ||
| 
						 | 
					abe8c897fd | ||
| 
						 | 
					e9d645b3b3 | ||
| 
						 | 
					7f0966c13d | ||
| 
						 | 
					55295f7b07 | ||
| 
						 | 
					9d25d7a2e6 | ||
| 
						 | 
					490cbaa89e | ||
| 
						 | 
					eb0bde09bb | ||
| 
						 | 
					3b12e1b011 | ||
| 
						 | 
					2138779559 | ||
| 
						 | 
					12943ea0c1 | ||
| 
						 | 
					6efb43a210 | ||
| 
						 | 
					03cc48474c | ||
| 
						 | 
					5672563f7e | ||
| 
						 | 
					106743c66b | ||
| 
						 | 
					8890dfa634 | ||
| 
						 | 
					10f32dbfbf | ||
| 
						 | 
					e35eeae8e0 | ||
| 
						 | 
					abbb6b9088 | ||
| 
						 | 
					3f35a3708a | ||
| 
						 | 
					33eafe050b | ||
| 
						 | 
					1d1b98f4a4 | ||
| 
						 | 
					a0ac30faa5 | ||
| 
						 | 
					49e3d5a9c9 | ||
| 
						 | 
					3338135ead | ||
| 
						 | 
					5dbfc78aff | ||
| 
						 | 
					7bc5552512 | ||
| 
						 | 
					a330b864e5 | ||
| 
						 | 
					7df419b434 | ||
| 
						 | 
					7cedfd753b | ||
| 
						 | 
					23b8e29835 | ||
| 
						 | 
					1c3287f1db | ||
| 
						 | 
					922ae9a5bf | ||
| 
						 | 
					189d6bf4d4 | ||
| 
						 | 
					c8f37cb4d6 | ||
| 
						 | 
					c0dcc3c60c | ||
| 
						 | 
					230e4fc270 | ||
| 
						 | 
					ead2f60f73 | ||
| 
						 | 
					f8bfbe8b14 | ||
| 
						 | 
					ffd75e420c | ||
| 
						 | 
					01d24a3281 | ||
| 
						 | 
					0be3ce66c0 | ||
| 
						 | 
					fcd0655176 | ||
| 
						 | 
					48454983c4 | ||
| 
						 | 
					9a3543a8d4 | ||
| 
						 | 
					465446b4b4 | ||
| 
						 | 
					b597b4fc9d | ||
| 
						 | 
					d20910c655 | ||
| 
						 | 
					677f4ad968 | ||
| 
						 | 
					7c20c9de5a | ||
| 
						 | 
					839fc954d0 | ||
| 
						 | 
					d164b05655 | ||
| 
						 | 
					a896f9cdeb | ||
| 
						 | 
					1b0cf6fa1c | ||
| 
						 | 
					9bf7c53779 | ||
| 
						 | 
					6be0fdb5e4 | ||
| 
						 | 
					641c4d47b9 | ||
| 
						 | 
					c1b9fa158e | ||
| 
						 | 
					6a421f1b6f | ||
| 
						 | 
					f1889d8640 | ||
| 
						 | 
					2982e42d93 | ||
| 
						 | 
					ddf1f9d7d5 | ||
| 
						 | 
					653c4ff354 | ||
| 
						 | 
					4efce88a62 | 
							
								
								
									
										563
									
								
								.clang-format
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										563
									
								
								.clang-format
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,563 @@
 | 
				
			|||||||
 | 
					# SPDX-License-Identifier: GPL-2.0
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# clang-format configuration file. Intended for clang-format >= 4.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# For more information, see:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#   Documentation/process/clang-format.rst
 | 
				
			||||||
 | 
					#   https://clang.llvm.org/docs/ClangFormat.html
 | 
				
			||||||
 | 
					#   https://clang.llvm.org/docs/ClangFormatStyleOptions.html
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					AccessModifierOffset: -4
 | 
				
			||||||
 | 
					AlignAfterOpenBracket: Align
 | 
				
			||||||
 | 
					AlignConsecutiveAssignments: false
 | 
				
			||||||
 | 
					AlignConsecutiveDeclarations: false
 | 
				
			||||||
 | 
					#AlignEscapedNewlines: Left # Unknown to clang-format-4.0
 | 
				
			||||||
 | 
					AlignOperands: true
 | 
				
			||||||
 | 
					AlignTrailingComments: false
 | 
				
			||||||
 | 
					AllowAllParametersOfDeclarationOnNextLine: false
 | 
				
			||||||
 | 
					AllowShortBlocksOnASingleLine: false
 | 
				
			||||||
 | 
					AllowShortCaseLabelsOnASingleLine: false
 | 
				
			||||||
 | 
					AllowShortFunctionsOnASingleLine: None
 | 
				
			||||||
 | 
					AllowShortIfStatementsOnASingleLine: false
 | 
				
			||||||
 | 
					AllowShortLoopsOnASingleLine: false
 | 
				
			||||||
 | 
					AlwaysBreakAfterDefinitionReturnType: None
 | 
				
			||||||
 | 
					AlwaysBreakAfterReturnType: None
 | 
				
			||||||
 | 
					AlwaysBreakBeforeMultilineStrings: false
 | 
				
			||||||
 | 
					AlwaysBreakTemplateDeclarations: false
 | 
				
			||||||
 | 
					BinPackArguments: true
 | 
				
			||||||
 | 
					BinPackParameters: true
 | 
				
			||||||
 | 
					BraceWrapping:
 | 
				
			||||||
 | 
					  AfterClass: false
 | 
				
			||||||
 | 
					  AfterControlStatement: false
 | 
				
			||||||
 | 
					  AfterEnum: false
 | 
				
			||||||
 | 
					  AfterFunction: true
 | 
				
			||||||
 | 
					  AfterNamespace: true
 | 
				
			||||||
 | 
					  AfterObjCDeclaration: false
 | 
				
			||||||
 | 
					  AfterStruct: false
 | 
				
			||||||
 | 
					  AfterUnion: false
 | 
				
			||||||
 | 
					  #AfterExternBlock: false # Unknown to clang-format-5.0
 | 
				
			||||||
 | 
					  BeforeCatch: false
 | 
				
			||||||
 | 
					  BeforeElse: false
 | 
				
			||||||
 | 
					  IndentBraces: false
 | 
				
			||||||
 | 
					  #SplitEmptyFunction: true # Unknown to clang-format-4.0
 | 
				
			||||||
 | 
					  #SplitEmptyRecord: true # Unknown to clang-format-4.0
 | 
				
			||||||
 | 
					  #SplitEmptyNamespace: true # Unknown to clang-format-4.0
 | 
				
			||||||
 | 
					BreakBeforeBinaryOperators: None
 | 
				
			||||||
 | 
					BreakBeforeBraces: Custom
 | 
				
			||||||
 | 
					#BreakBeforeInheritanceComma: false # Unknown to clang-format-4.0
 | 
				
			||||||
 | 
					BreakBeforeTernaryOperators: false
 | 
				
			||||||
 | 
					BreakConstructorInitializersBeforeComma: false
 | 
				
			||||||
 | 
					#BreakConstructorInitializers: BeforeComma # Unknown to clang-format-4.0
 | 
				
			||||||
 | 
					BreakAfterJavaFieldAnnotations: false
 | 
				
			||||||
 | 
					BreakStringLiterals: false
 | 
				
			||||||
 | 
					ColumnLimit: 120
 | 
				
			||||||
 | 
					CommentPragmas: '^ IWYU pragma:'
 | 
				
			||||||
 | 
					#CompactNamespaces: false # Unknown to clang-format-4.0
 | 
				
			||||||
 | 
					ConstructorInitializerAllOnOneLineOrOnePerLine: false
 | 
				
			||||||
 | 
					ConstructorInitializerIndentWidth: 8
 | 
				
			||||||
 | 
					ContinuationIndentWidth: 8
 | 
				
			||||||
 | 
					Cpp11BracedListStyle: false
 | 
				
			||||||
 | 
					DerivePointerAlignment: false
 | 
				
			||||||
 | 
					DisableFormat: false
 | 
				
			||||||
 | 
					ExperimentalAutoDetectBinPacking: false
 | 
				
			||||||
 | 
					#FixNamespaceComments: false # Unknown to clang-format-4.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Taken from:
 | 
				
			||||||
 | 
					#   git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ \
 | 
				
			||||||
 | 
					#   | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$,  - '\1'," \
 | 
				
			||||||
 | 
					#   | sort | uniq
 | 
				
			||||||
 | 
					ForEachMacros:
 | 
				
			||||||
 | 
					  - 'apei_estatus_for_each_section'
 | 
				
			||||||
 | 
					  - 'ata_for_each_dev'
 | 
				
			||||||
 | 
					  - 'ata_for_each_link'
 | 
				
			||||||
 | 
					  - '__ata_qc_for_each'
 | 
				
			||||||
 | 
					  - 'ata_qc_for_each'
 | 
				
			||||||
 | 
					  - 'ata_qc_for_each_raw'
 | 
				
			||||||
 | 
					  - 'ata_qc_for_each_with_internal'
 | 
				
			||||||
 | 
					  - 'ax25_for_each'
 | 
				
			||||||
 | 
					  - 'ax25_uid_for_each'
 | 
				
			||||||
 | 
					  - '__bio_for_each_bvec'
 | 
				
			||||||
 | 
					  - 'bio_for_each_bvec'
 | 
				
			||||||
 | 
					  - 'bio_for_each_bvec_all'
 | 
				
			||||||
 | 
					  - 'bio_for_each_integrity_vec'
 | 
				
			||||||
 | 
					  - '__bio_for_each_segment'
 | 
				
			||||||
 | 
					  - 'bio_for_each_segment'
 | 
				
			||||||
 | 
					  - 'bio_for_each_segment_all'
 | 
				
			||||||
 | 
					  - 'bio_list_for_each'
 | 
				
			||||||
 | 
					  - 'bip_for_each_vec'
 | 
				
			||||||
 | 
					  - 'bitmap_for_each_clear_region'
 | 
				
			||||||
 | 
					  - 'bitmap_for_each_set_region'
 | 
				
			||||||
 | 
					  - 'blkg_for_each_descendant_post'
 | 
				
			||||||
 | 
					  - 'blkg_for_each_descendant_pre'
 | 
				
			||||||
 | 
					  - 'blk_queue_for_each_rl'
 | 
				
			||||||
 | 
					  - 'bond_for_each_slave'
 | 
				
			||||||
 | 
					  - 'bond_for_each_slave_rcu'
 | 
				
			||||||
 | 
					  - 'bpf_for_each_spilled_reg'
 | 
				
			||||||
 | 
					  - 'btree_for_each_safe128'
 | 
				
			||||||
 | 
					  - 'btree_for_each_safe32'
 | 
				
			||||||
 | 
					  - 'btree_for_each_safe64'
 | 
				
			||||||
 | 
					  - 'btree_for_each_safel'
 | 
				
			||||||
 | 
					  - 'card_for_each_dev'
 | 
				
			||||||
 | 
					  - 'cgroup_taskset_for_each'
 | 
				
			||||||
 | 
					  - 'cgroup_taskset_for_each_leader'
 | 
				
			||||||
 | 
					  - 'cpufreq_for_each_entry'
 | 
				
			||||||
 | 
					  - 'cpufreq_for_each_entry_idx'
 | 
				
			||||||
 | 
					  - 'cpufreq_for_each_valid_entry'
 | 
				
			||||||
 | 
					  - 'cpufreq_for_each_valid_entry_idx'
 | 
				
			||||||
 | 
					  - 'css_for_each_child'
 | 
				
			||||||
 | 
					  - 'css_for_each_descendant_post'
 | 
				
			||||||
 | 
					  - 'css_for_each_descendant_pre'
 | 
				
			||||||
 | 
					  - 'device_for_each_child_node'
 | 
				
			||||||
 | 
					  - 'displayid_iter_for_each'
 | 
				
			||||||
 | 
					  - 'dma_fence_chain_for_each'
 | 
				
			||||||
 | 
					  - 'do_for_each_ftrace_op'
 | 
				
			||||||
 | 
					  - 'drm_atomic_crtc_for_each_plane'
 | 
				
			||||||
 | 
					  - 'drm_atomic_crtc_state_for_each_plane'
 | 
				
			||||||
 | 
					  - 'drm_atomic_crtc_state_for_each_plane_state'
 | 
				
			||||||
 | 
					  - 'drm_atomic_for_each_plane_damage'
 | 
				
			||||||
 | 
					  - 'drm_client_for_each_connector_iter'
 | 
				
			||||||
 | 
					  - 'drm_client_for_each_modeset'
 | 
				
			||||||
 | 
					  - 'drm_connector_for_each_possible_encoder'
 | 
				
			||||||
 | 
					  - 'drm_for_each_bridge_in_chain'
 | 
				
			||||||
 | 
					  - 'drm_for_each_connector_iter'
 | 
				
			||||||
 | 
					  - 'drm_for_each_crtc'
 | 
				
			||||||
 | 
					  - 'drm_for_each_crtc_reverse'
 | 
				
			||||||
 | 
					  - 'drm_for_each_encoder'
 | 
				
			||||||
 | 
					  - 'drm_for_each_encoder_mask'
 | 
				
			||||||
 | 
					  - 'drm_for_each_fb'
 | 
				
			||||||
 | 
					  - 'drm_for_each_legacy_plane'
 | 
				
			||||||
 | 
					  - 'drm_for_each_plane'
 | 
				
			||||||
 | 
					  - 'drm_for_each_plane_mask'
 | 
				
			||||||
 | 
					  - 'drm_for_each_privobj'
 | 
				
			||||||
 | 
					  - 'drm_mm_for_each_hole'
 | 
				
			||||||
 | 
					  - 'drm_mm_for_each_node'
 | 
				
			||||||
 | 
					  - 'drm_mm_for_each_node_in_range'
 | 
				
			||||||
 | 
					  - 'drm_mm_for_each_node_safe'
 | 
				
			||||||
 | 
					  - 'flow_action_for_each'
 | 
				
			||||||
 | 
					  - 'for_each_acpi_dev_match'
 | 
				
			||||||
 | 
					  - 'for_each_active_dev_scope'
 | 
				
			||||||
 | 
					  - 'for_each_active_drhd_unit'
 | 
				
			||||||
 | 
					  - 'for_each_active_iommu'
 | 
				
			||||||
 | 
					  - 'for_each_aggr_pgid'
 | 
				
			||||||
 | 
					  - 'for_each_available_child_of_node'
 | 
				
			||||||
 | 
					  - 'for_each_bio'
 | 
				
			||||||
 | 
					  - 'for_each_board_func_rsrc'
 | 
				
			||||||
 | 
					  - 'for_each_bvec'
 | 
				
			||||||
 | 
					  - 'for_each_card_auxs'
 | 
				
			||||||
 | 
					  - 'for_each_card_auxs_safe'
 | 
				
			||||||
 | 
					  - 'for_each_card_components'
 | 
				
			||||||
 | 
					  - 'for_each_card_dapms'
 | 
				
			||||||
 | 
					  - 'for_each_card_pre_auxs'
 | 
				
			||||||
 | 
					  - 'for_each_card_prelinks'
 | 
				
			||||||
 | 
					  - 'for_each_card_rtds'
 | 
				
			||||||
 | 
					  - 'for_each_card_rtds_safe'
 | 
				
			||||||
 | 
					  - 'for_each_card_widgets'
 | 
				
			||||||
 | 
					  - 'for_each_card_widgets_safe'
 | 
				
			||||||
 | 
					  - 'for_each_cgroup_storage_type'
 | 
				
			||||||
 | 
					  - 'for_each_child_of_node'
 | 
				
			||||||
 | 
					  - 'for_each_clear_bit'
 | 
				
			||||||
 | 
					  - 'for_each_clear_bit_from'
 | 
				
			||||||
 | 
					  - 'for_each_cmsghdr'
 | 
				
			||||||
 | 
					  - 'for_each_compatible_node'
 | 
				
			||||||
 | 
					  - 'for_each_component_dais'
 | 
				
			||||||
 | 
					  - 'for_each_component_dais_safe'
 | 
				
			||||||
 | 
					  - 'for_each_comp_order'
 | 
				
			||||||
 | 
					  - 'for_each_console'
 | 
				
			||||||
 | 
					  - 'for_each_cpu'
 | 
				
			||||||
 | 
					  - 'for_each_cpu_and'
 | 
				
			||||||
 | 
					  - 'for_each_cpu_not'
 | 
				
			||||||
 | 
					  - 'for_each_cpu_wrap'
 | 
				
			||||||
 | 
					  - 'for_each_dapm_widgets'
 | 
				
			||||||
 | 
					  - 'for_each_dev_addr'
 | 
				
			||||||
 | 
					  - 'for_each_dev_scope'
 | 
				
			||||||
 | 
					  - 'for_each_dma_cap_mask'
 | 
				
			||||||
 | 
					  - 'for_each_dpcm_be'
 | 
				
			||||||
 | 
					  - 'for_each_dpcm_be_rollback'
 | 
				
			||||||
 | 
					  - 'for_each_dpcm_be_safe'
 | 
				
			||||||
 | 
					  - 'for_each_dpcm_fe'
 | 
				
			||||||
 | 
					  - 'for_each_drhd_unit'
 | 
				
			||||||
 | 
					  - 'for_each_dss_dev'
 | 
				
			||||||
 | 
					  - 'for_each_dtpm_table'
 | 
				
			||||||
 | 
					  - 'for_each_efi_memory_desc'
 | 
				
			||||||
 | 
					  - 'for_each_efi_memory_desc_in_map'
 | 
				
			||||||
 | 
					  - 'for_each_element'
 | 
				
			||||||
 | 
					  - 'for_each_element_extid'
 | 
				
			||||||
 | 
					  - 'for_each_element_id'
 | 
				
			||||||
 | 
					  - 'for_each_endpoint_of_node'
 | 
				
			||||||
 | 
					  - 'for_each_evictable_lru'
 | 
				
			||||||
 | 
					  - 'for_each_fib6_node_rt_rcu'
 | 
				
			||||||
 | 
					  - 'for_each_fib6_walker_rt'
 | 
				
			||||||
 | 
					  - 'for_each_free_mem_pfn_range_in_zone'
 | 
				
			||||||
 | 
					  - 'for_each_free_mem_pfn_range_in_zone_from'
 | 
				
			||||||
 | 
					  - 'for_each_free_mem_range'
 | 
				
			||||||
 | 
					  - 'for_each_free_mem_range_reverse'
 | 
				
			||||||
 | 
					  - 'for_each_func_rsrc'
 | 
				
			||||||
 | 
					  - 'for_each_hstate'
 | 
				
			||||||
 | 
					  - 'for_each_if'
 | 
				
			||||||
 | 
					  - 'for_each_iommu'
 | 
				
			||||||
 | 
					  - 'for_each_ip_tunnel_rcu'
 | 
				
			||||||
 | 
					  - 'for_each_irq_nr'
 | 
				
			||||||
 | 
					  - 'for_each_link_codecs'
 | 
				
			||||||
 | 
					  - 'for_each_link_cpus'
 | 
				
			||||||
 | 
					  - 'for_each_link_platforms'
 | 
				
			||||||
 | 
					  - 'for_each_lru'
 | 
				
			||||||
 | 
					  - 'for_each_matching_node'
 | 
				
			||||||
 | 
					  - 'for_each_matching_node_and_match'
 | 
				
			||||||
 | 
					  - 'for_each_member'
 | 
				
			||||||
 | 
					  - 'for_each_memcg_cache_index'
 | 
				
			||||||
 | 
					  - 'for_each_mem_pfn_range'
 | 
				
			||||||
 | 
					  - '__for_each_mem_range'
 | 
				
			||||||
 | 
					  - 'for_each_mem_range'
 | 
				
			||||||
 | 
					  - '__for_each_mem_range_rev'
 | 
				
			||||||
 | 
					  - 'for_each_mem_range_rev'
 | 
				
			||||||
 | 
					  - 'for_each_mem_region'
 | 
				
			||||||
 | 
					  - 'for_each_migratetype_order'
 | 
				
			||||||
 | 
					  - 'for_each_msi_entry'
 | 
				
			||||||
 | 
					  - 'for_each_msi_entry_safe'
 | 
				
			||||||
 | 
					  - 'for_each_msi_vector'
 | 
				
			||||||
 | 
					  - 'for_each_net'
 | 
				
			||||||
 | 
					  - 'for_each_net_continue_reverse'
 | 
				
			||||||
 | 
					  - 'for_each_netdev'
 | 
				
			||||||
 | 
					  - 'for_each_netdev_continue'
 | 
				
			||||||
 | 
					  - 'for_each_netdev_continue_rcu'
 | 
				
			||||||
 | 
					  - 'for_each_netdev_continue_reverse'
 | 
				
			||||||
 | 
					  - 'for_each_netdev_feature'
 | 
				
			||||||
 | 
					  - 'for_each_netdev_in_bond_rcu'
 | 
				
			||||||
 | 
					  - 'for_each_netdev_rcu'
 | 
				
			||||||
 | 
					  - 'for_each_netdev_reverse'
 | 
				
			||||||
 | 
					  - 'for_each_netdev_safe'
 | 
				
			||||||
 | 
					  - 'for_each_net_rcu'
 | 
				
			||||||
 | 
					  - 'for_each_new_connector_in_state'
 | 
				
			||||||
 | 
					  - 'for_each_new_crtc_in_state'
 | 
				
			||||||
 | 
					  - 'for_each_new_mst_mgr_in_state'
 | 
				
			||||||
 | 
					  - 'for_each_new_plane_in_state'
 | 
				
			||||||
 | 
					  - 'for_each_new_private_obj_in_state'
 | 
				
			||||||
 | 
					  - 'for_each_node'
 | 
				
			||||||
 | 
					  - 'for_each_node_by_name'
 | 
				
			||||||
 | 
					  - 'for_each_node_by_type'
 | 
				
			||||||
 | 
					  - 'for_each_node_mask'
 | 
				
			||||||
 | 
					  - 'for_each_node_state'
 | 
				
			||||||
 | 
					  - 'for_each_node_with_cpus'
 | 
				
			||||||
 | 
					  - 'for_each_node_with_property'
 | 
				
			||||||
 | 
					  - 'for_each_nonreserved_multicast_dest_pgid'
 | 
				
			||||||
 | 
					  - 'for_each_of_allnodes'
 | 
				
			||||||
 | 
					  - 'for_each_of_allnodes_from'
 | 
				
			||||||
 | 
					  - 'for_each_of_cpu_node'
 | 
				
			||||||
 | 
					  - 'for_each_of_pci_range'
 | 
				
			||||||
 | 
					  - 'for_each_old_connector_in_state'
 | 
				
			||||||
 | 
					  - 'for_each_old_crtc_in_state'
 | 
				
			||||||
 | 
					  - 'for_each_old_mst_mgr_in_state'
 | 
				
			||||||
 | 
					  - 'for_each_oldnew_connector_in_state'
 | 
				
			||||||
 | 
					  - 'for_each_oldnew_crtc_in_state'
 | 
				
			||||||
 | 
					  - 'for_each_oldnew_mst_mgr_in_state'
 | 
				
			||||||
 | 
					  - 'for_each_oldnew_plane_in_state'
 | 
				
			||||||
 | 
					  - 'for_each_oldnew_plane_in_state_reverse'
 | 
				
			||||||
 | 
					  - 'for_each_oldnew_private_obj_in_state'
 | 
				
			||||||
 | 
					  - 'for_each_old_plane_in_state'
 | 
				
			||||||
 | 
					  - 'for_each_old_private_obj_in_state'
 | 
				
			||||||
 | 
					  - 'for_each_online_cpu'
 | 
				
			||||||
 | 
					  - 'for_each_online_node'
 | 
				
			||||||
 | 
					  - 'for_each_online_pgdat'
 | 
				
			||||||
 | 
					  - 'for_each_pci_bridge'
 | 
				
			||||||
 | 
					  - 'for_each_pci_dev'
 | 
				
			||||||
 | 
					  - 'for_each_pci_msi_entry'
 | 
				
			||||||
 | 
					  - 'for_each_pcm_streams'
 | 
				
			||||||
 | 
					  - 'for_each_physmem_range'
 | 
				
			||||||
 | 
					  - 'for_each_populated_zone'
 | 
				
			||||||
 | 
					  - 'for_each_possible_cpu'
 | 
				
			||||||
 | 
					  - 'for_each_present_cpu'
 | 
				
			||||||
 | 
					  - 'for_each_prime_number'
 | 
				
			||||||
 | 
					  - 'for_each_prime_number_from'
 | 
				
			||||||
 | 
					  - 'for_each_process'
 | 
				
			||||||
 | 
					  - 'for_each_process_thread'
 | 
				
			||||||
 | 
					  - 'for_each_prop_codec_conf'
 | 
				
			||||||
 | 
					  - 'for_each_prop_dai_codec'
 | 
				
			||||||
 | 
					  - 'for_each_prop_dai_cpu'
 | 
				
			||||||
 | 
					  - 'for_each_prop_dlc_codecs'
 | 
				
			||||||
 | 
					  - 'for_each_prop_dlc_cpus'
 | 
				
			||||||
 | 
					  - 'for_each_prop_dlc_platforms'
 | 
				
			||||||
 | 
					  - 'for_each_property_of_node'
 | 
				
			||||||
 | 
					  - 'for_each_registered_fb'
 | 
				
			||||||
 | 
					  - 'for_each_requested_gpio'
 | 
				
			||||||
 | 
					  - 'for_each_requested_gpio_in_range'
 | 
				
			||||||
 | 
					  - 'for_each_reserved_mem_range'
 | 
				
			||||||
 | 
					  - 'for_each_reserved_mem_region'
 | 
				
			||||||
 | 
					  - 'for_each_rtd_codec_dais'
 | 
				
			||||||
 | 
					  - 'for_each_rtd_components'
 | 
				
			||||||
 | 
					  - 'for_each_rtd_cpu_dais'
 | 
				
			||||||
 | 
					  - 'for_each_rtd_dais'
 | 
				
			||||||
 | 
					  - 'for_each_set_bit'
 | 
				
			||||||
 | 
					  - 'for_each_set_bit_from'
 | 
				
			||||||
 | 
					  - 'for_each_set_clump8'
 | 
				
			||||||
 | 
					  - 'for_each_sg'
 | 
				
			||||||
 | 
					  - 'for_each_sg_dma_page'
 | 
				
			||||||
 | 
					  - 'for_each_sg_page'
 | 
				
			||||||
 | 
					  - 'for_each_sgtable_dma_page'
 | 
				
			||||||
 | 
					  - 'for_each_sgtable_dma_sg'
 | 
				
			||||||
 | 
					  - 'for_each_sgtable_page'
 | 
				
			||||||
 | 
					  - 'for_each_sgtable_sg'
 | 
				
			||||||
 | 
					  - 'for_each_sibling_event'
 | 
				
			||||||
 | 
					  - 'for_each_subelement'
 | 
				
			||||||
 | 
					  - 'for_each_subelement_extid'
 | 
				
			||||||
 | 
					  - 'for_each_subelement_id'
 | 
				
			||||||
 | 
					  - '__for_each_thread'
 | 
				
			||||||
 | 
					  - 'for_each_thread'
 | 
				
			||||||
 | 
					  - 'for_each_unicast_dest_pgid'
 | 
				
			||||||
 | 
					  - 'for_each_vsi'
 | 
				
			||||||
 | 
					  - 'for_each_wakeup_source'
 | 
				
			||||||
 | 
					  - 'for_each_zone'
 | 
				
			||||||
 | 
					  - 'for_each_zone_zonelist'
 | 
				
			||||||
 | 
					  - 'for_each_zone_zonelist_nodemask'
 | 
				
			||||||
 | 
					  - 'fwnode_for_each_available_child_node'
 | 
				
			||||||
 | 
					  - 'fwnode_for_each_child_node'
 | 
				
			||||||
 | 
					  - 'fwnode_graph_for_each_endpoint'
 | 
				
			||||||
 | 
					  - 'gadget_for_each_ep'
 | 
				
			||||||
 | 
					  - 'genradix_for_each'
 | 
				
			||||||
 | 
					  - 'genradix_for_each_from'
 | 
				
			||||||
 | 
					  - 'hash_for_each'
 | 
				
			||||||
 | 
					  - 'hash_for_each_possible'
 | 
				
			||||||
 | 
					  - 'hash_for_each_possible_rcu'
 | 
				
			||||||
 | 
					  - 'hash_for_each_possible_rcu_notrace'
 | 
				
			||||||
 | 
					  - 'hash_for_each_possible_safe'
 | 
				
			||||||
 | 
					  - 'hash_for_each_rcu'
 | 
				
			||||||
 | 
					  - 'hash_for_each_safe'
 | 
				
			||||||
 | 
					  - 'hctx_for_each_ctx'
 | 
				
			||||||
 | 
					  - 'hlist_bl_for_each_entry'
 | 
				
			||||||
 | 
					  - 'hlist_bl_for_each_entry_rcu'
 | 
				
			||||||
 | 
					  - 'hlist_bl_for_each_entry_safe'
 | 
				
			||||||
 | 
					  - 'hlist_for_each'
 | 
				
			||||||
 | 
					  - 'hlist_for_each_entry'
 | 
				
			||||||
 | 
					  - 'hlist_for_each_entry_continue'
 | 
				
			||||||
 | 
					  - 'hlist_for_each_entry_continue_rcu'
 | 
				
			||||||
 | 
					  - 'hlist_for_each_entry_continue_rcu_bh'
 | 
				
			||||||
 | 
					  - 'hlist_for_each_entry_from'
 | 
				
			||||||
 | 
					  - 'hlist_for_each_entry_from_rcu'
 | 
				
			||||||
 | 
					  - 'hlist_for_each_entry_rcu'
 | 
				
			||||||
 | 
					  - 'hlist_for_each_entry_rcu_bh'
 | 
				
			||||||
 | 
					  - 'hlist_for_each_entry_rcu_notrace'
 | 
				
			||||||
 | 
					  - 'hlist_for_each_entry_safe'
 | 
				
			||||||
 | 
					  - 'hlist_for_each_entry_srcu'
 | 
				
			||||||
 | 
					  - '__hlist_for_each_rcu'
 | 
				
			||||||
 | 
					  - 'hlist_for_each_safe'
 | 
				
			||||||
 | 
					  - 'hlist_nulls_for_each_entry'
 | 
				
			||||||
 | 
					  - 'hlist_nulls_for_each_entry_from'
 | 
				
			||||||
 | 
					  - 'hlist_nulls_for_each_entry_rcu'
 | 
				
			||||||
 | 
					  - 'hlist_nulls_for_each_entry_safe'
 | 
				
			||||||
 | 
					  - 'i3c_bus_for_each_i2cdev'
 | 
				
			||||||
 | 
					  - 'i3c_bus_for_each_i3cdev'
 | 
				
			||||||
 | 
					  - 'ide_host_for_each_port'
 | 
				
			||||||
 | 
					  - 'ide_port_for_each_dev'
 | 
				
			||||||
 | 
					  - 'ide_port_for_each_present_dev'
 | 
				
			||||||
 | 
					  - 'idr_for_each_entry'
 | 
				
			||||||
 | 
					  - 'idr_for_each_entry_continue'
 | 
				
			||||||
 | 
					  - 'idr_for_each_entry_continue_ul'
 | 
				
			||||||
 | 
					  - 'idr_for_each_entry_ul'
 | 
				
			||||||
 | 
					  - 'in_dev_for_each_ifa_rcu'
 | 
				
			||||||
 | 
					  - 'in_dev_for_each_ifa_rtnl'
 | 
				
			||||||
 | 
					  - 'inet_bind_bucket_for_each'
 | 
				
			||||||
 | 
					  - 'inet_lhash2_for_each_icsk_rcu'
 | 
				
			||||||
 | 
					  - 'key_for_each'
 | 
				
			||||||
 | 
					  - 'key_for_each_safe'
 | 
				
			||||||
 | 
					  - 'klp_for_each_func'
 | 
				
			||||||
 | 
					  - 'klp_for_each_func_safe'
 | 
				
			||||||
 | 
					  - 'klp_for_each_func_static'
 | 
				
			||||||
 | 
					  - 'klp_for_each_object'
 | 
				
			||||||
 | 
					  - 'klp_for_each_object_safe'
 | 
				
			||||||
 | 
					  - 'klp_for_each_object_static'
 | 
				
			||||||
 | 
					  - 'kunit_suite_for_each_test_case'
 | 
				
			||||||
 | 
					  - 'kvm_for_each_memslot'
 | 
				
			||||||
 | 
					  - 'kvm_for_each_vcpu'
 | 
				
			||||||
 | 
					  - 'list_for_each'
 | 
				
			||||||
 | 
					  - 'list_for_each_codec'
 | 
				
			||||||
 | 
					  - 'list_for_each_codec_safe'
 | 
				
			||||||
 | 
					  - 'list_for_each_continue'
 | 
				
			||||||
 | 
					  - 'list_for_each_entry'
 | 
				
			||||||
 | 
					  - 'list_for_each_entry_continue'
 | 
				
			||||||
 | 
					  - 'list_for_each_entry_continue_rcu'
 | 
				
			||||||
 | 
					  - 'list_for_each_entry_continue_reverse'
 | 
				
			||||||
 | 
					  - 'list_for_each_entry_from'
 | 
				
			||||||
 | 
					  - 'list_for_each_entry_from_rcu'
 | 
				
			||||||
 | 
					  - 'list_for_each_entry_from_reverse'
 | 
				
			||||||
 | 
					  - 'list_for_each_entry_lockless'
 | 
				
			||||||
 | 
					  - 'list_for_each_entry_rcu'
 | 
				
			||||||
 | 
					  - 'list_for_each_entry_reverse'
 | 
				
			||||||
 | 
					  - 'list_for_each_entry_safe'
 | 
				
			||||||
 | 
					  - 'list_for_each_entry_safe_continue'
 | 
				
			||||||
 | 
					  - 'list_for_each_entry_safe_from'
 | 
				
			||||||
 | 
					  - 'list_for_each_entry_safe_reverse'
 | 
				
			||||||
 | 
					  - 'list_for_each_entry_srcu'
 | 
				
			||||||
 | 
					  - 'list_for_each_prev'
 | 
				
			||||||
 | 
					  - 'list_for_each_prev_safe'
 | 
				
			||||||
 | 
					  - 'list_for_each_safe'
 | 
				
			||||||
 | 
					  - 'llist_for_each'
 | 
				
			||||||
 | 
					  - 'llist_for_each_entry'
 | 
				
			||||||
 | 
					  - 'llist_for_each_entry_safe'
 | 
				
			||||||
 | 
					  - 'llist_for_each_safe'
 | 
				
			||||||
 | 
					  - 'mci_for_each_dimm'
 | 
				
			||||||
 | 
					  - 'media_device_for_each_entity'
 | 
				
			||||||
 | 
					  - 'media_device_for_each_intf'
 | 
				
			||||||
 | 
					  - 'media_device_for_each_link'
 | 
				
			||||||
 | 
					  - 'media_device_for_each_pad'
 | 
				
			||||||
 | 
					  - 'nanddev_io_for_each_page'
 | 
				
			||||||
 | 
					  - 'netdev_for_each_lower_dev'
 | 
				
			||||||
 | 
					  - 'netdev_for_each_lower_private'
 | 
				
			||||||
 | 
					  - 'netdev_for_each_lower_private_rcu'
 | 
				
			||||||
 | 
					  - 'netdev_for_each_mc_addr'
 | 
				
			||||||
 | 
					  - 'netdev_for_each_uc_addr'
 | 
				
			||||||
 | 
					  - 'netdev_for_each_upper_dev_rcu'
 | 
				
			||||||
 | 
					  - 'netdev_hw_addr_list_for_each'
 | 
				
			||||||
 | 
					  - 'nft_rule_for_each_expr'
 | 
				
			||||||
 | 
					  - 'nla_for_each_attr'
 | 
				
			||||||
 | 
					  - 'nla_for_each_nested'
 | 
				
			||||||
 | 
					  - 'nlmsg_for_each_attr'
 | 
				
			||||||
 | 
					  - 'nlmsg_for_each_msg'
 | 
				
			||||||
 | 
					  - 'nr_neigh_for_each'
 | 
				
			||||||
 | 
					  - 'nr_neigh_for_each_safe'
 | 
				
			||||||
 | 
					  - 'nr_node_for_each'
 | 
				
			||||||
 | 
					  - 'nr_node_for_each_safe'
 | 
				
			||||||
 | 
					  - 'of_for_each_phandle'
 | 
				
			||||||
 | 
					  - 'of_property_for_each_string'
 | 
				
			||||||
 | 
					  - 'of_property_for_each_u32'
 | 
				
			||||||
 | 
					  - 'pci_bus_for_each_resource'
 | 
				
			||||||
 | 
					  - 'pcl_for_each_chunk'
 | 
				
			||||||
 | 
					  - 'pcl_for_each_segment'
 | 
				
			||||||
 | 
					  - 'pcm_for_each_format'
 | 
				
			||||||
 | 
					  - 'ping_portaddr_for_each_entry'
 | 
				
			||||||
 | 
					  - 'plist_for_each'
 | 
				
			||||||
 | 
					  - 'plist_for_each_continue'
 | 
				
			||||||
 | 
					  - 'plist_for_each_entry'
 | 
				
			||||||
 | 
					  - 'plist_for_each_entry_continue'
 | 
				
			||||||
 | 
					  - 'plist_for_each_entry_safe'
 | 
				
			||||||
 | 
					  - 'plist_for_each_safe'
 | 
				
			||||||
 | 
					  - 'pnp_for_each_card'
 | 
				
			||||||
 | 
					  - 'pnp_for_each_dev'
 | 
				
			||||||
 | 
					  - 'protocol_for_each_card'
 | 
				
			||||||
 | 
					  - 'protocol_for_each_dev'
 | 
				
			||||||
 | 
					  - 'queue_for_each_hw_ctx'
 | 
				
			||||||
 | 
					  - 'radix_tree_for_each_slot'
 | 
				
			||||||
 | 
					  - 'radix_tree_for_each_tagged'
 | 
				
			||||||
 | 
					  - 'rb_for_each'
 | 
				
			||||||
 | 
					  - 'rbtree_postorder_for_each_entry_safe'
 | 
				
			||||||
 | 
					  - 'rdma_for_each_block'
 | 
				
			||||||
 | 
					  - 'rdma_for_each_port'
 | 
				
			||||||
 | 
					  - 'rdma_umem_for_each_dma_block'
 | 
				
			||||||
 | 
					  - 'resource_list_for_each_entry'
 | 
				
			||||||
 | 
					  - 'resource_list_for_each_entry_safe'
 | 
				
			||||||
 | 
					  - 'rhl_for_each_entry_rcu'
 | 
				
			||||||
 | 
					  - 'rhl_for_each_rcu'
 | 
				
			||||||
 | 
					  - 'rht_for_each'
 | 
				
			||||||
 | 
					  - 'rht_for_each_entry'
 | 
				
			||||||
 | 
					  - 'rht_for_each_entry_from'
 | 
				
			||||||
 | 
					  - 'rht_for_each_entry_rcu'
 | 
				
			||||||
 | 
					  - 'rht_for_each_entry_rcu_from'
 | 
				
			||||||
 | 
					  - 'rht_for_each_entry_safe'
 | 
				
			||||||
 | 
					  - 'rht_for_each_from'
 | 
				
			||||||
 | 
					  - 'rht_for_each_rcu'
 | 
				
			||||||
 | 
					  - 'rht_for_each_rcu_from'
 | 
				
			||||||
 | 
					  - '__rq_for_each_bio'
 | 
				
			||||||
 | 
					  - 'rq_for_each_bvec'
 | 
				
			||||||
 | 
					  - 'rq_for_each_segment'
 | 
				
			||||||
 | 
					  - 'scsi_for_each_prot_sg'
 | 
				
			||||||
 | 
					  - 'scsi_for_each_sg'
 | 
				
			||||||
 | 
					  - 'sctp_for_each_hentry'
 | 
				
			||||||
 | 
					  - 'sctp_skb_for_each'
 | 
				
			||||||
 | 
					  - 'shdma_for_each_chan'
 | 
				
			||||||
 | 
					  - '__shost_for_each_device'
 | 
				
			||||||
 | 
					  - 'shost_for_each_device'
 | 
				
			||||||
 | 
					  - 'sk_for_each'
 | 
				
			||||||
 | 
					  - 'sk_for_each_bound'
 | 
				
			||||||
 | 
					  - 'sk_for_each_entry_offset_rcu'
 | 
				
			||||||
 | 
					  - 'sk_for_each_from'
 | 
				
			||||||
 | 
					  - 'sk_for_each_rcu'
 | 
				
			||||||
 | 
					  - 'sk_for_each_safe'
 | 
				
			||||||
 | 
					  - 'sk_nulls_for_each'
 | 
				
			||||||
 | 
					  - 'sk_nulls_for_each_from'
 | 
				
			||||||
 | 
					  - 'sk_nulls_for_each_rcu'
 | 
				
			||||||
 | 
					  - 'snd_array_for_each'
 | 
				
			||||||
 | 
					  - 'snd_pcm_group_for_each_entry'
 | 
				
			||||||
 | 
					  - 'snd_soc_dapm_widget_for_each_path'
 | 
				
			||||||
 | 
					  - 'snd_soc_dapm_widget_for_each_path_safe'
 | 
				
			||||||
 | 
					  - 'snd_soc_dapm_widget_for_each_sink_path'
 | 
				
			||||||
 | 
					  - 'snd_soc_dapm_widget_for_each_source_path'
 | 
				
			||||||
 | 
					  - 'tb_property_for_each'
 | 
				
			||||||
 | 
					  - 'tcf_exts_for_each_action'
 | 
				
			||||||
 | 
					  - 'udp_portaddr_for_each_entry'
 | 
				
			||||||
 | 
					  - 'udp_portaddr_for_each_entry_rcu'
 | 
				
			||||||
 | 
					  - 'usb_hub_for_each_child'
 | 
				
			||||||
 | 
					  - 'v4l2_device_for_each_subdev'
 | 
				
			||||||
 | 
					  - 'v4l2_m2m_for_each_dst_buf'
 | 
				
			||||||
 | 
					  - 'v4l2_m2m_for_each_dst_buf_safe'
 | 
				
			||||||
 | 
					  - 'v4l2_m2m_for_each_src_buf'
 | 
				
			||||||
 | 
					  - 'v4l2_m2m_for_each_src_buf_safe'
 | 
				
			||||||
 | 
					  - 'virtio_device_for_each_vq'
 | 
				
			||||||
 | 
					  - 'while_for_each_ftrace_op'
 | 
				
			||||||
 | 
					  - 'xa_for_each'
 | 
				
			||||||
 | 
					  - 'xa_for_each_marked'
 | 
				
			||||||
 | 
					  - 'xa_for_each_range'
 | 
				
			||||||
 | 
					  - 'xa_for_each_start'
 | 
				
			||||||
 | 
					  - 'xas_for_each'
 | 
				
			||||||
 | 
					  - 'xas_for_each_conflict'
 | 
				
			||||||
 | 
					  - 'xas_for_each_marked'
 | 
				
			||||||
 | 
					  - 'xbc_array_for_each_value'
 | 
				
			||||||
 | 
					  - 'xbc_for_each_key_value'
 | 
				
			||||||
 | 
					  - 'xbc_node_for_each_array_value'
 | 
				
			||||||
 | 
					  - 'xbc_node_for_each_child'
 | 
				
			||||||
 | 
					  - 'xbc_node_for_each_key_value'
 | 
				
			||||||
 | 
					  - 'zorro_for_each_dev'
 | 
				
			||||||
 | 
					  - 'for_each_line'
 | 
				
			||||||
 | 
					  - 'for_each_non_empty_line'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#IncludeBlocks: Preserve # Unknown to clang-format-5.0
 | 
				
			||||||
 | 
					IncludeCategories:
 | 
				
			||||||
 | 
					  - Regex: '.*'
 | 
				
			||||||
 | 
					    Priority: 1
 | 
				
			||||||
 | 
					IncludeIsMainRegex: '(Test)?$'
 | 
				
			||||||
 | 
					IndentCaseLabels: false
 | 
				
			||||||
 | 
					#IndentPPDirectives: None # Unknown to clang-format-5.0
 | 
				
			||||||
 | 
					IndentWidth: 8
 | 
				
			||||||
 | 
					IndentWrappedFunctionNames: false
 | 
				
			||||||
 | 
					JavaScriptQuotes: Leave
 | 
				
			||||||
 | 
					JavaScriptWrapImports: true
 | 
				
			||||||
 | 
					KeepEmptyLinesAtTheStartOfBlocks: false
 | 
				
			||||||
 | 
					MacroBlockBegin: ''
 | 
				
			||||||
 | 
					MacroBlockEnd: ''
 | 
				
			||||||
 | 
					MaxEmptyLinesToKeep: 1
 | 
				
			||||||
 | 
					NamespaceIndentation: None
 | 
				
			||||||
 | 
					#ObjCBinPackProtocolList: Auto # Unknown to clang-format-5.0
 | 
				
			||||||
 | 
					ObjCBlockIndentWidth: 8
 | 
				
			||||||
 | 
					ObjCSpaceAfterProperty: true
 | 
				
			||||||
 | 
					ObjCSpaceBeforeProtocolList: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Taken from git's rules
 | 
				
			||||||
 | 
					#PenaltyBreakAssignment: 10 # Unknown to clang-format-4.0
 | 
				
			||||||
 | 
					PenaltyBreakBeforeFirstCallParameter: 30
 | 
				
			||||||
 | 
					PenaltyBreakComment: 10
 | 
				
			||||||
 | 
					PenaltyBreakFirstLessLess: 0
 | 
				
			||||||
 | 
					PenaltyBreakString: 10
 | 
				
			||||||
 | 
					PenaltyExcessCharacter: 100
 | 
				
			||||||
 | 
					PenaltyReturnTypeOnItsOwnLine: 60
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PointerAlignment: Right
 | 
				
			||||||
 | 
					ReflowComments: false
 | 
				
			||||||
 | 
					SortIncludes: false
 | 
				
			||||||
 | 
					#SortUsingDeclarations: false # Unknown to clang-format-4.0
 | 
				
			||||||
 | 
					SpaceAfterCStyleCast: false
 | 
				
			||||||
 | 
					SpaceAfterTemplateKeyword: true
 | 
				
			||||||
 | 
					SpaceBeforeAssignmentOperators: true
 | 
				
			||||||
 | 
					#SpaceBeforeCtorInitializerColon: true # Unknown to clang-format-5.0
 | 
				
			||||||
 | 
					#SpaceBeforeInheritanceColon: true # Unknown to clang-format-5.0
 | 
				
			||||||
 | 
					SpaceBeforeParens: ControlStatements
 | 
				
			||||||
 | 
					#SpaceBeforeRangeBasedForLoopColon: true # Unknown to clang-format-5.0
 | 
				
			||||||
 | 
					SpaceInEmptyParentheses: false
 | 
				
			||||||
 | 
					SpacesBeforeTrailingComments: 1
 | 
				
			||||||
 | 
					SpacesInAngles: false
 | 
				
			||||||
 | 
					SpacesInContainerLiterals: false
 | 
				
			||||||
 | 
					SpacesInCStyleCastParentheses: false
 | 
				
			||||||
 | 
					SpacesInParentheses: false
 | 
				
			||||||
 | 
					SpacesInSquareBrackets: false
 | 
				
			||||||
 | 
					Standard: Cpp03
 | 
				
			||||||
 | 
					TabWidth: 8
 | 
				
			||||||
 | 
					UseTab: Always
 | 
				
			||||||
 | 
					...
 | 
				
			||||||
							
								
								
									
										58
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										58
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -2,26 +2,21 @@ debian/*.log
 | 
				
			|||||||
*.o
 | 
					*.o
 | 
				
			||||||
*.lo
 | 
					*.lo
 | 
				
			||||||
*.a
 | 
					*.a
 | 
				
			||||||
 | 
					*.la
 | 
				
			||||||
.deps
 | 
					.deps
 | 
				
			||||||
Makefile
 | 
					Makefile
 | 
				
			||||||
Makefile.in
 | 
					Makefile.in
 | 
				
			||||||
bscconfig.h
 | 
					bscconfig.h
 | 
				
			||||||
bscconfig.h.in
 | 
					bscconfig.h.in
 | 
				
			||||||
openbsc.pc
 | 
					src/osmo-mgw/osmo-mgw
 | 
				
			||||||
src/osmo-nitb/osmo-nitb
 | 
					 | 
				
			||||||
src/osmo-bsc_mgcp/osmo-bsc_mgcp
 | 
					 | 
				
			||||||
src/osmo-bsc/osmo-bsc
 | 
					 | 
				
			||||||
src/utils/meas_vis
 | 
					 | 
				
			||||||
src/utils/meas_json
 | 
					 | 
				
			||||||
src/utils/osmo-meas-pcap2db
 | 
					 | 
				
			||||||
src/utils/osmo-meas-udp2db
 | 
					 | 
				
			||||||
src/utils/smpp_mirror
 | 
					 | 
				
			||||||
*.*~
 | 
					*.*~
 | 
				
			||||||
*.sw?
 | 
					*.sw?
 | 
				
			||||||
.libs
 | 
					.libs
 | 
				
			||||||
*.pyc
 | 
					*.pyc
 | 
				
			||||||
*.gcda
 | 
					*.gcda
 | 
				
			||||||
*.gcno
 | 
					*.gcno
 | 
				
			||||||
 | 
					*.pc
 | 
				
			||||||
 | 
					*~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#configure
 | 
					#configure
 | 
				
			||||||
aclocal.m4
 | 
					aclocal.m4
 | 
				
			||||||
@@ -38,38 +33,16 @@ missing
 | 
				
			|||||||
stamp-h1
 | 
					stamp-h1
 | 
				
			||||||
libtool
 | 
					libtool
 | 
				
			||||||
ltmain.sh
 | 
					ltmain.sh
 | 
				
			||||||
 | 
					m4/*.m4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# git-version-gen magic
 | 
					# git-version-gen magic
 | 
				
			||||||
.tarball-version
 | 
					.tarball-version
 | 
				
			||||||
.version
 | 
					.version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# apps and app data
 | 
					 | 
				
			||||||
hlr.sqlite3
 | 
					 | 
				
			||||||
src/utils/bs11_config
 | 
					 | 
				
			||||||
src/ipaccess/ipaccess-config
 | 
					 | 
				
			||||||
src/ipaccess/abisip-find
 | 
					 | 
				
			||||||
src/ipaccess/ipaccess-firmware
 | 
					 | 
				
			||||||
src/ipaccess/ipaccess-proxy
 | 
					 | 
				
			||||||
src/utils/isdnsync
 | 
					 | 
				
			||||||
src/nat/bsc_nat
 | 
					 | 
				
			||||||
src/gprs/osmo-sgsn
 | 
					 | 
				
			||||||
src/gprs/osmo-gbproxy
 | 
					 | 
				
			||||||
src/gprs/osmo-gtphub
 | 
					 | 
				
			||||||
src/osmo-bsc_nat/osmo-bsc_nat
 | 
					 | 
				
			||||||
src/libcommon/gsup_test_client
 | 
					 | 
				
			||||||
src/osmo-msc/osmo-msc
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#tests
 | 
					#tests
 | 
				
			||||||
tests/testsuite.dir
 | 
					tests/testsuite.dir
 | 
				
			||||||
tests/*/*_test
 | 
					tests/*/*_test
 | 
				
			||||||
# ignore compiled binaries like msc_vlr_test_foo; do not ignore
 | 
					 | 
				
			||||||
# msc_vlr_test_foo.{c,ok,err}, but do still ignore the corresponding .o object
 | 
					 | 
				
			||||||
# files:
 | 
					 | 
				
			||||||
tests/msc_vlr/msc_vlr_test_*
 | 
					 | 
				
			||||||
!tests/msc_vlr/msc_vlr_test_*.*
 | 
					 | 
				
			||||||
tests/msc_vlr/msc_vlr_test_*.o
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
tests/atconfig
 | 
					tests/atconfig
 | 
				
			||||||
tests/atlocal
 | 
					tests/atlocal
 | 
				
			||||||
@@ -77,7 +50,22 @@ tests/package.m4
 | 
				
			|||||||
tests/testsuite
 | 
					tests/testsuite
 | 
				
			||||||
tests/testsuite.log
 | 
					tests/testsuite.log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gsn_restart
 | 
					 | 
				
			||||||
src/openbsc.cfg*
 | 
					 | 
				
			||||||
writtenconfig/
 | 
					writtenconfig/
 | 
				
			||||||
gtphub_restart_count
 | 
					
 | 
				
			||||||
 | 
					# manuals
 | 
				
			||||||
 | 
					doc/manuals/*.html
 | 
				
			||||||
 | 
					doc/manuals/*.svg
 | 
				
			||||||
 | 
					doc/manuals/*.pdf
 | 
				
			||||||
 | 
					doc/manuals/*__*.png
 | 
				
			||||||
 | 
					doc/manuals/*.check
 | 
				
			||||||
 | 
					doc/manuals/generated/
 | 
				
			||||||
 | 
					doc/manuals/osmomsc-usermanual.xml
 | 
				
			||||||
 | 
					doc/manuals/common
 | 
				
			||||||
 | 
					doc/manuals/build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					contrib/osmo-mgw.spec
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#vs code
 | 
				
			||||||
 | 
					.cache
 | 
				
			||||||
 | 
					.vscode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										15
									
								
								Makefile.am
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								Makefile.am
									
									
									
									
									
								
							@@ -9,22 +9,29 @@ AM_CPPFLAGS = \
 | 
				
			|||||||
	$(NULL)
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SUBDIRS = \
 | 
					SUBDIRS = \
 | 
				
			||||||
	doc \
 | 
					 | 
				
			||||||
	include \
 | 
						include \
 | 
				
			||||||
	src \
 | 
						src \
 | 
				
			||||||
	tests \
 | 
						tests \
 | 
				
			||||||
 | 
						doc \
 | 
				
			||||||
	contrib \
 | 
						contrib \
 | 
				
			||||||
	$(NULL)
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pkgconfigdir = $(libdir)/pkgconfig
 | 
					pkgconfigdir = $(libdir)/pkgconfig
 | 
				
			||||||
pkgconfig_DATA = \
 | 
					pkgconfig_DATA = \
 | 
				
			||||||
	libosmo-legacy-mgcp.pc \
 | 
					 | 
				
			||||||
	libosmo-mgcp-client.pc \
 | 
						libosmo-mgcp-client.pc \
 | 
				
			||||||
	libosmo-mgcp.pc \
 | 
					 | 
				
			||||||
	$(NULL)
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BUILT_SOURCES = $(top_srcdir)/.version
 | 
					BUILT_SOURCES = $(top_srcdir)/.version
 | 
				
			||||||
EXTRA_DIST = git-version-gen osmoappdesc.py .version
 | 
					EXTRA_DIST = \
 | 
				
			||||||
 | 
						     .version \
 | 
				
			||||||
 | 
						     contrib/osmo-mgw.spec.in \
 | 
				
			||||||
 | 
						     debian \
 | 
				
			||||||
 | 
						     git-version-gen \
 | 
				
			||||||
 | 
						     osmoappdesc.py \
 | 
				
			||||||
 | 
						     $(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AM_DISTCHECK_CONFIGURE_FLAGS = \
 | 
				
			||||||
 | 
						--with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@RELMAKE@
 | 
					@RELMAKE@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										4
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								README
									
									
									
									
									
								
							@@ -19,10 +19,6 @@ OsmoBSC, and receives and sends RTP streams as configured via MGCP.
 | 
				
			|||||||
The libosmo-mgcp-client library exposes utilities used by e.g. OsmoMSC (found
 | 
					The libosmo-mgcp-client library exposes utilities used by e.g. OsmoMSC (found
 | 
				
			||||||
in osmo-msc.git) to instruct OsmoMGW via its MGCP service.
 | 
					in osmo-msc.git) to instruct OsmoMGW via its MGCP service.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The libosmo-mgcp library exposes MGCP server utilities used by e.g. OsmoBSC-NAT
 | 
					 | 
				
			||||||
(found in osmo-bsc.git) to navigate RTP streams through a NAT.
 | 
					 | 
				
			||||||
(At time of writing, this is still called libosmo-legacy-mgcp.)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Find OsmoMGW issue tracker and wiki online at
 | 
					Find OsmoMGW issue tracker and wiki online at
 | 
				
			||||||
https://osmocom.org/projects/osmo-mgw
 | 
					https://osmocom.org/projects/osmo-mgw
 | 
				
			||||||
https://osmocom.org/projects/osmo-mgw/wiki
 | 
					https://osmocom.org/projects/osmo-mgw/wiki
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										156
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										156
									
								
								configure.ac
									
									
									
									
									
								
							@@ -9,6 +9,8 @@ AC_CONFIG_AUX_DIR([.])
 | 
				
			|||||||
AM_INIT_AUTOMAKE([dist-bzip2])
 | 
					AM_INIT_AUTOMAKE([dist-bzip2])
 | 
				
			||||||
AC_CONFIG_TESTDIR(tests)
 | 
					AC_CONFIG_TESTDIR(tests)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CFLAGS="$CFLAGS -std=gnu11"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dnl kernel style compile messages
 | 
					dnl kernel style compile messages
 | 
				
			||||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
 | 
					m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -22,6 +24,11 @@ AC_PROG_CC
 | 
				
			|||||||
AC_PROG_INSTALL
 | 
					AC_PROG_INSTALL
 | 
				
			||||||
LT_INIT
 | 
					LT_INIT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dnl patching ${archive_cmds} to affect generation of file "libtool" to fix linking with clang
 | 
				
			||||||
 | 
					AS_CASE(["$LD"],[*clang*],
 | 
				
			||||||
 | 
					  [AS_CASE(["${host_os}"],
 | 
				
			||||||
 | 
					     [*linux*],[archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'])])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dnl check for pkg-config (explained in detail in libosmocore/configure.ac)
 | 
					dnl check for pkg-config (explained in detail in libosmocore/configure.ac)
 | 
				
			||||||
AC_PATH_PROG(PKG_CONFIG_INSTALLED, pkg-config, no)
 | 
					AC_PATH_PROG(PKG_CONFIG_INSTALLED, pkg-config, no)
 | 
				
			||||||
if test "x$PKG_CONFIG_INSTALLED" = "xno"; then
 | 
					if test "x$PKG_CONFIG_INSTALLED" = "xno"; then
 | 
				
			||||||
@@ -29,55 +36,54 @@ if test "x$PKG_CONFIG_INSTALLED" = "xno"; then
 | 
				
			|||||||
fi
 | 
					fi
 | 
				
			||||||
PKG_PROG_PKG_CONFIG([0.20])
 | 
					PKG_PROG_PKG_CONFIG([0.20])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dnl check for AX_CHECK_COMPILE_FLAG
 | 
					 | 
				
			||||||
m4_ifdef([AX_CHECK_COMPILE_FLAG], [], [
 | 
					 | 
				
			||||||
	AC_MSG_ERROR([Please install autoconf-archive; re-run 'autoreconf -fi' for it to take effect.])
 | 
					 | 
				
			||||||
	])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
dnl checks for libraries
 | 
					dnl checks for libraries
 | 
				
			||||||
AC_SEARCH_LIBS([dlopen], [dl dld], [LIBRARY_DL="$LIBS";LIBS=""])
 | 
					AC_SEARCH_LIBS([dlopen], [dl dld], [LIBRARY_DL="$LIBS";LIBS=""])
 | 
				
			||||||
AC_SUBST(LIBRARY_DL)
 | 
					AC_SUBST(LIBRARY_DL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AC_SEARCH_LIBS([dlsym], [dl dld], [LIBRARY_DLSYM="$LIBS";LIBS=""])
 | 
				
			||||||
 | 
					AC_SUBST(LIBRARY_DLSYM)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.10.0)
 | 
					 | 
				
			||||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 0.10.0)
 | 
					 | 
				
			||||||
PKG_CHECK_MODULES(LIBOSMONETIF, libosmo-netif >= 0.1.0)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Enable/disable transcoding within osmo-bsc_mgcp?
 | 
					PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.6.0)
 | 
				
			||||||
AC_ARG_ENABLE([mgcp-transcoding], [AS_HELP_STRING([--enable-mgcp-transcoding], [Build the MGCP gateway with internal transcoding enabled.])],
 | 
					PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.6.0)
 | 
				
			||||||
    [osmo_ac_mgcp_transcoding="$enableval"],[osmo_ac_mgcp_transcoding="no"])
 | 
					PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.6.0)
 | 
				
			||||||
AC_ARG_WITH([g729], [AS_HELP_STRING([--with-g729], [Enable G.729 encoding/decoding.])], [osmo_ac_with_g729="$withval"],[osmo_ac_with_g729="no"])
 | 
					PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.6.0)
 | 
				
			||||||
 | 
					PKG_CHECK_MODULES(LIBOSMONETIF, libosmo-netif >= 1.1.0)
 | 
				
			||||||
 | 
					PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 1.2.0)
 | 
				
			||||||
 | 
					PKG_CHECK_MODULES(LIBOSMOTRAU, libosmotrau >= 1.2.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if test "$osmo_ac_mgcp_transcoding" = "yes" ; then
 | 
					CFLAGS="$CFLAGS -pthread"
 | 
				
			||||||
    AC_SEARCH_LIBS([gsm_create], [gsm], [LIBRARY_GSM="$LIBS";LIBS=""], [AC_MSG_ERROR([--enable-mgcp-transcoding: cannot find usable libgsm])])
 | 
					LDFLAGS="$LDFLAGS -pthread"
 | 
				
			||||||
    AC_SUBST(LIBRARY_GSM)
 | 
					
 | 
				
			||||||
    if test "$osmo_ac_with_g729" = "yes" ; then
 | 
					AC_ARG_ENABLE(sanitize,
 | 
				
			||||||
	PKG_CHECK_MODULES(LIBBCG729, libbcg729 >= 0.1, [AC_DEFINE([HAVE_BCG729], [1], [Use bgc729 decoder/encoder])])
 | 
						[AS_HELP_STRING(
 | 
				
			||||||
 | 
							[--enable-sanitize],
 | 
				
			||||||
 | 
							[Compile with address sanitizer enabled],
 | 
				
			||||||
 | 
						)],
 | 
				
			||||||
 | 
						[sanitize=$enableval], [sanitize="no"])
 | 
				
			||||||
 | 
					if test x"$sanitize" = x"yes"
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						CFLAGS="$CFLAGS -fsanitize=address -fsanitize=undefined"
 | 
				
			||||||
 | 
						CPPFLAGS="$CPPFLAGS -fsanitize=address -fsanitize=undefined"
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
    AC_DEFINE(BUILD_MGCP_TRANSCODING, 1, [Define if we want to build the MGCP gateway with transcoding support])
 | 
					
 | 
				
			||||||
 | 
					AC_ARG_ENABLE(werror,
 | 
				
			||||||
 | 
						[AS_HELP_STRING(
 | 
				
			||||||
 | 
							[--enable-werror],
 | 
				
			||||||
 | 
							[Turn all compiler warnings into errors, with exceptions:
 | 
				
			||||||
 | 
							 a) deprecation (allow upstream to mark deprecation without breaking builds);
 | 
				
			||||||
 | 
							 b) "#warning" pragmas (allow to remind ourselves of errors without breaking builds)
 | 
				
			||||||
 | 
							]
 | 
				
			||||||
 | 
						)],
 | 
				
			||||||
 | 
						[werror=$enableval], [werror="no"])
 | 
				
			||||||
 | 
					if test x"$werror" = x"yes"
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						WERROR_FLAGS="-Werror"
 | 
				
			||||||
 | 
						WERROR_FLAGS+=" -Wno-error=deprecated -Wno-error=deprecated-declarations"
 | 
				
			||||||
 | 
						WERROR_FLAGS+=" -Wno-error=cpp" # "#warning"
 | 
				
			||||||
 | 
						CFLAGS="$CFLAGS $WERROR_FLAGS"
 | 
				
			||||||
 | 
						CPPFLAGS="$CPPFLAGS $WERROR_FLAGS"
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
AM_CONDITIONAL(BUILD_MGCP_TRANSCODING, test "x$osmo_ac_mgcp_transcoding" = "xyes")
 | 
					 | 
				
			||||||
AC_SUBST(osmo_ac_mgcp_transcoding)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
dnl Checks for typedefs, structures and compiler characteristics
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# The following test is taken from WebKit's webkit.m4
 | 
					 | 
				
			||||||
saved_CFLAGS="$CFLAGS"
 | 
					 | 
				
			||||||
CFLAGS="$CFLAGS -fvisibility=hidden "
 | 
					 | 
				
			||||||
AC_MSG_CHECKING([if ${CC} supports -fvisibility=hidden])
 | 
					 | 
				
			||||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([char foo;])],
 | 
					 | 
				
			||||||
      [ AC_MSG_RESULT([yes])
 | 
					 | 
				
			||||||
        SYMBOL_VISIBILITY="-fvisibility=hidden"],
 | 
					 | 
				
			||||||
        AC_MSG_RESULT([no]))
 | 
					 | 
				
			||||||
CFLAGS="$saved_CFLAGS"
 | 
					 | 
				
			||||||
AC_SUBST(SYMBOL_VISIBILITY)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
AX_CHECK_COMPILE_FLAG([-Werror=implicit], [CFLAGS="$CFLAGS -Werror=implicit"])
 | 
					 | 
				
			||||||
AX_CHECK_COMPILE_FLAG([-Werror=maybe-uninitialized], [CFLAGS="$CFLAGS -Werror=maybe-uninitialized"])
 | 
					 | 
				
			||||||
AX_CHECK_COMPILE_FLAG([-Werror=memset-transposed-args], [CFLAGS="$CFLAGS -Werror=memset-transposed-args"])
 | 
					 | 
				
			||||||
AX_CHECK_COMPILE_FLAG([-Werror=null-dereference], [CFLAGS="$CFLAGS -Werror=null-dereference"])
 | 
					 | 
				
			||||||
AX_CHECK_COMPILE_FLAG([-Werror=sizeof-array-argument], [CFLAGS="$CFLAGS -Werror=sizeof-array-argument"])
 | 
					 | 
				
			||||||
AX_CHECK_COMPILE_FLAG([-Werror=sizeof-pointer-memaccess], [CFLAGS="$CFLAGS -Werror=sizeof-pointer-memaccess"])
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Coverage build taken from WebKit's configure.in
 | 
					# Coverage build taken from WebKit's configure.in
 | 
				
			||||||
AC_MSG_CHECKING([whether to enable code coverage support])
 | 
					AC_MSG_CHECKING([whether to enable code coverage support])
 | 
				
			||||||
@@ -113,30 +119,88 @@ AC_MSG_CHECKING([whether to enable VTY/CTRL tests])
 | 
				
			|||||||
AC_MSG_RESULT([$enable_ext_tests])
 | 
					AC_MSG_RESULT([$enable_ext_tests])
 | 
				
			||||||
AM_CONDITIONAL(ENABLE_EXT_TESTS, test "x$enable_ext_tests" = "xyes")
 | 
					AM_CONDITIONAL(ENABLE_EXT_TESTS, test "x$enable_ext_tests" = "xyes")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Generate manuals
 | 
				
			||||||
 | 
					AC_ARG_ENABLE(manuals,
 | 
				
			||||||
 | 
						[AS_HELP_STRING(
 | 
				
			||||||
 | 
							[--enable-manuals],
 | 
				
			||||||
 | 
							[Generate manual PDFs [default=no]],
 | 
				
			||||||
 | 
						)],
 | 
				
			||||||
 | 
						[osmo_ac_build_manuals=$enableval], [osmo_ac_build_manuals="no"])
 | 
				
			||||||
 | 
					AM_CONDITIONAL([BUILD_MANUALS], [test x"$osmo_ac_build_manuals" = x"yes"])
 | 
				
			||||||
 | 
					AC_ARG_VAR(OSMO_GSM_MANUALS_DIR, [path to common osmo-gsm-manuals files, overriding pkg-config and "../osmo-gsm-manuals"
 | 
				
			||||||
 | 
						fallback])
 | 
				
			||||||
 | 
					if test x"$osmo_ac_build_manuals" = x"yes"
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						# Find OSMO_GSM_MANUALS_DIR (env, pkg-conf, fallback)
 | 
				
			||||||
 | 
						if test -n "$OSMO_GSM_MANUALS_DIR"; then
 | 
				
			||||||
 | 
							echo "checking for OSMO_GSM_MANUALS_DIR... $OSMO_GSM_MANUALS_DIR (from env)"
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							OSMO_GSM_MANUALS_DIR="$($PKG_CONFIG osmo-gsm-manuals --variable=osmogsmmanualsdir 2>/dev/null)"
 | 
				
			||||||
 | 
							if test -n "$OSMO_GSM_MANUALS_DIR"; then
 | 
				
			||||||
 | 
								echo "checking for OSMO_GSM_MANUALS_DIR... $OSMO_GSM_MANUALS_DIR (from pkg-conf)"
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								OSMO_GSM_MANUALS_DIR="../osmo-gsm-manuals"
 | 
				
			||||||
 | 
								echo "checking for OSMO_GSM_MANUALS_DIR... $OSMO_GSM_MANUALS_DIR (fallback)"
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
						if ! test -d "$OSMO_GSM_MANUALS_DIR"; then
 | 
				
			||||||
 | 
							AC_MSG_ERROR("OSMO_GSM_MANUALS_DIR does not exist! Install osmo-gsm-manuals or set OSMO_GSM_MANUALS_DIR.")
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						# Find and run check-depends
 | 
				
			||||||
 | 
						CHECK_DEPENDS="$OSMO_GSM_MANUALS_DIR/check-depends.sh"
 | 
				
			||||||
 | 
						if ! test -x "$CHECK_DEPENDS"; then
 | 
				
			||||||
 | 
							CHECK_DEPENDS="osmo-gsm-manuals-check-depends"
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
						if ! $CHECK_DEPENDS; then
 | 
				
			||||||
 | 
							AC_MSG_ERROR("missing dependencies for --enable-manuals")
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						# Put in Makefile with absolute path
 | 
				
			||||||
 | 
						OSMO_GSM_MANUALS_DIR="$(realpath "$OSMO_GSM_MANUALS_DIR")"
 | 
				
			||||||
 | 
						AC_SUBST([OSMO_GSM_MANUALS_DIR])
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# https://www.freedesktop.org/software/systemd/man/daemon.html
 | 
				
			||||||
 | 
					AC_ARG_WITH([systemdsystemunitdir],
 | 
				
			||||||
 | 
					     [AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files])],,
 | 
				
			||||||
 | 
					     [with_systemdsystemunitdir=auto])
 | 
				
			||||||
 | 
					AS_IF([test "x$with_systemdsystemunitdir" = "xyes" -o "x$with_systemdsystemunitdir" = "xauto"], [
 | 
				
			||||||
 | 
					     def_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     AS_IF([test "x$def_systemdsystemunitdir" = "x"],
 | 
				
			||||||
 | 
					   [AS_IF([test "x$with_systemdsystemunitdir" = "xyes"],
 | 
				
			||||||
 | 
					    [AC_MSG_ERROR([systemd support requested but pkg-config unable to query systemd package])])
 | 
				
			||||||
 | 
					    with_systemdsystemunitdir=no],
 | 
				
			||||||
 | 
					   [with_systemdsystemunitdir="$def_systemdsystemunitdir"])])
 | 
				
			||||||
 | 
					AS_IF([test "x$with_systemdsystemunitdir" != "xno"],
 | 
				
			||||||
 | 
					      [AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])])
 | 
				
			||||||
 | 
					AM_CONDITIONAL([HAVE_SYSTEMD], [test "x$with_systemdsystemunitdir" != "xno"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AC_MSG_RESULT([CFLAGS="$CFLAGS"])
 | 
				
			||||||
 | 
					AC_MSG_RESULT([CPPFLAGS="$CPPFLAGS"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dnl Generate the output
 | 
					dnl Generate the output
 | 
				
			||||||
AM_CONFIG_HEADER(bscconfig.h)
 | 
					AM_CONFIG_HEADER(bscconfig.h)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AC_OUTPUT(
 | 
					AC_OUTPUT(
 | 
				
			||||||
    libosmo-legacy-mgcp.pc
 | 
					 | 
				
			||||||
    libosmo-mgcp-client.pc
 | 
					    libosmo-mgcp-client.pc
 | 
				
			||||||
    libosmo-mgcp.pc
 | 
					 | 
				
			||||||
    include/Makefile
 | 
					    include/Makefile
 | 
				
			||||||
    include/osmocom/Makefile
 | 
					    include/osmocom/Makefile
 | 
				
			||||||
    include/osmocom/legacy_mgcp/Makefile
 | 
					 | 
				
			||||||
    include/osmocom/mgcp_client/Makefile
 | 
					    include/osmocom/mgcp_client/Makefile
 | 
				
			||||||
    include/osmocom/mgcp/Makefile
 | 
					    include/osmocom/mgcp/Makefile
 | 
				
			||||||
    src/Makefile
 | 
					    src/Makefile
 | 
				
			||||||
    src/libosmo-legacy-mgcp/Makefile
 | 
					 | 
				
			||||||
    src/libosmo-mgcp-client/Makefile
 | 
					    src/libosmo-mgcp-client/Makefile
 | 
				
			||||||
    src/libosmo-mgcp/Makefile
 | 
					    src/libosmo-mgcp/Makefile
 | 
				
			||||||
    src/osmo-bsc_mgcp/Makefile
 | 
					 | 
				
			||||||
    src/osmo-mgw/Makefile
 | 
					    src/osmo-mgw/Makefile
 | 
				
			||||||
    tests/Makefile
 | 
					    tests/Makefile
 | 
				
			||||||
    tests/atlocal
 | 
					    tests/atlocal
 | 
				
			||||||
    tests/legacy_mgcp/Makefile
 | 
					 | 
				
			||||||
    tests/mgcp_client/Makefile
 | 
					    tests/mgcp_client/Makefile
 | 
				
			||||||
    tests/mgcp/Makefile
 | 
					    tests/mgcp/Makefile
 | 
				
			||||||
    doc/Makefile
 | 
					    doc/Makefile
 | 
				
			||||||
    doc/examples/Makefile
 | 
					    doc/examples/Makefile
 | 
				
			||||||
 | 
					    doc/manuals/Makefile
 | 
				
			||||||
    contrib/Makefile
 | 
					    contrib/Makefile
 | 
				
			||||||
 | 
					    contrib/systemd/Makefile
 | 
				
			||||||
 | 
					    contrib/osmo-mgw.spec
 | 
				
			||||||
    Makefile)
 | 
					    Makefile)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1 +1,3 @@
 | 
				
			|||||||
 | 
					SUBDIRS = systemd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EXTRA_DIST = ipa.py
 | 
					EXTRA_DIST = ipa.py
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,10 @@
 | 
				
			|||||||
#!/usr/bin/env bash
 | 
					#!/usr/bin/env bash
 | 
				
			||||||
# jenkins build helper script for openbsc.  This is how we build on jenkins.osmocom.org
 | 
					# jenkins build helper script for openbsc.  This is how we build on jenkins.osmocom.org
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# environment variables:
 | 
				
			||||||
 | 
					# * WITH_MANUALS: build manual PDFs if set to "1"
 | 
				
			||||||
 | 
					# * PUBLISH: upload manuals after building if set to "1" (ignored without WITH_MANUALS = "1")
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if ! [ -x "$(command -v osmo-build-dep.sh)" ]; then
 | 
					if ! [ -x "$(command -v osmo-build-dep.sh)" ]; then
 | 
				
			||||||
	echo "Error: We need to have scripts/osmo-deps.sh from http://git.osmocom.org/osmo-ci/ in PATH !"
 | 
						echo "Error: We need to have scripts/osmo-deps.sh from http://git.osmocom.org/osmo-ci/ in PATH !"
 | 
				
			||||||
@@ -23,10 +28,17 @@ verify_value_string_arrays_are_terminated.py $(find . -name "*.[hc]")
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
 | 
					export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
 | 
				
			||||||
export LD_LIBRARY_PATH="$inst/lib"
 | 
					export LD_LIBRARY_PATH="$inst/lib"
 | 
				
			||||||
 | 
					export PATH="$inst/bin:$PATH"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
osmo-build-dep.sh libosmo-abis
 | 
					osmo-build-dep.sh libosmo-abis
 | 
				
			||||||
osmo-build-dep.sh libosmo-netif
 | 
					osmo-build-dep.sh libosmo-netif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Additional configure options and depends
 | 
				
			||||||
 | 
					CONFIG=""
 | 
				
			||||||
 | 
					if [ "$WITH_MANUALS" = "1" ]; then
 | 
				
			||||||
 | 
						CONFIG="--enable-manuals"
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set +x
 | 
					set +x
 | 
				
			||||||
echo
 | 
					echo
 | 
				
			||||||
echo
 | 
					echo
 | 
				
			||||||
@@ -37,13 +49,18 @@ set -x
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
cd "$base"
 | 
					cd "$base"
 | 
				
			||||||
autoreconf --install --force
 | 
					autoreconf --install --force
 | 
				
			||||||
./configure $MGCP --enable-vty-tests --enable-external-tests
 | 
					./configure --enable-sanitize --enable-vty-tests --enable-external-tests --enable-werror $CONFIG
 | 
				
			||||||
$MAKE $PARALLEL_MAKE
 | 
					$MAKE $PARALLEL_MAKE
 | 
				
			||||||
LD_LIBRARY_PATH="$inst/lib" $MAKE check \
 | 
					LD_LIBRARY_PATH="$inst/lib" $MAKE check \
 | 
				
			||||||
  || cat-testlogs.sh
 | 
					  || cat-testlogs.sh
 | 
				
			||||||
LD_LIBRARY_PATH="$inst/lib" \
 | 
					LD_LIBRARY_PATH="$inst/lib" \
 | 
				
			||||||
  DISTCHECK_CONFIGURE_FLAGS="$MGCP --enable-vty-tests --enable-external-tests" \
 | 
					  DISTCHECK_CONFIGURE_FLAGS="--enable-vty-tests --enable-external-tests $CONFIG" \
 | 
				
			||||||
  $MAKE distcheck \
 | 
					  $MAKE $PARALLEL_MAKE distcheck \
 | 
				
			||||||
  || cat-testlogs.sh
 | 
					  || cat-testlogs.sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [ "$WITH_MANUALS" = "1" ] && [ "$PUBLISH" = "1" ]; then
 | 
				
			||||||
 | 
						make -C "$base/doc/manuals" publish
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$MAKE $PARALLEL_MAKE maintainer-clean
 | 
				
			||||||
osmo-clean-workspace.sh
 | 
					osmo-clean-workspace.sh
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										137
									
								
								contrib/osmo-mgw.spec.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								contrib/osmo-mgw.spec.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,137 @@
 | 
				
			|||||||
 | 
					#
 | 
				
			||||||
 | 
					# spec file for package osmo-mgw
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (c) 2017, Martin Hauke <mardnh@gmx.de>
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# All modifications and additions to the file contributed by third parties
 | 
				
			||||||
 | 
					# remain the property of their copyright owners, unless otherwise agreed
 | 
				
			||||||
 | 
					# upon. The license for this file, and modifications and additions to the
 | 
				
			||||||
 | 
					# file, is the same license as for the pristine package itself (unless the
 | 
				
			||||||
 | 
					# license for the pristine package is not an Open Source License, in which
 | 
				
			||||||
 | 
					# case the license is the MIT License). An "Open Source License" is a
 | 
				
			||||||
 | 
					# license that conforms to the Open Source Definition (Version 1.9)
 | 
				
			||||||
 | 
					# published by the Open Source Initiative.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Please submit bugfixes or comments via http://bugs.opensuse.org/
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Name:           osmo-mgw
 | 
				
			||||||
 | 
					Version:        @VERSION@
 | 
				
			||||||
 | 
					Release:        0
 | 
				
			||||||
 | 
					Summary:        Osmocom's Media Gateway for 2G and 3G circuit-switched mobile networks
 | 
				
			||||||
 | 
					License:        AGPL-3.0-or-later AND GPL-2.0-or-later
 | 
				
			||||||
 | 
					Group:          Hardware/Mobile
 | 
				
			||||||
 | 
					URL:            https://osmocom.org/projects/osmo-mgw
 | 
				
			||||||
 | 
					Source:         %{name}-%{version}.tar.xz
 | 
				
			||||||
 | 
					BuildRequires:  automake >= 1.9
 | 
				
			||||||
 | 
					BuildRequires:  libtool >= 2
 | 
				
			||||||
 | 
					BuildRequires:  pkgconfig >= 0.20
 | 
				
			||||||
 | 
					%if 0%{?suse_version}
 | 
				
			||||||
 | 
					BuildRequires:  systemd-rpm-macros
 | 
				
			||||||
 | 
					%endif
 | 
				
			||||||
 | 
					BuildRequires:  pkgconfig(libosmo-netif) >= 1.1.0
 | 
				
			||||||
 | 
					BuildRequires:  pkgconfig(libosmocore) >= 1.6.0
 | 
				
			||||||
 | 
					BuildRequires:  pkgconfig(libosmoctrl) >= 1.6.0
 | 
				
			||||||
 | 
					BuildRequires:  pkgconfig(libosmogsm) >= 1.6.0
 | 
				
			||||||
 | 
					BuildRequires:  pkgconfig(libosmovty) >= 1.6.0
 | 
				
			||||||
 | 
					BuildRequires:  pkgconfig(libosmocoding) >= 1.6.0
 | 
				
			||||||
 | 
					BuildRequires:  pkgconfig(libosmoabis) >= 1.2.0
 | 
				
			||||||
 | 
					BuildRequires:  pkgconfig(libosmotrau) >= 1.2.0
 | 
				
			||||||
 | 
					%{?systemd_requires}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%description
 | 
				
			||||||
 | 
					OsmoMGW is Osmocom's Media Gateway for 2G and 3G circuit-switched mobile networks.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%package -n libosmo-mgcp-client9
 | 
				
			||||||
 | 
					Summary:        Osmocom's Media Gateway Control Protocol client library
 | 
				
			||||||
 | 
					Group:          System/Libraries
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%description -n libosmo-mgcp-client9
 | 
				
			||||||
 | 
					Osmocom's Media Gateway Control Protocol client library.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%package -n libosmo-mgcp-client-devel
 | 
				
			||||||
 | 
					Summary:        Development files for Osmocom's Media Gateway Control Protocol client library
 | 
				
			||||||
 | 
					Group:          Development/Libraries/C and C++
 | 
				
			||||||
 | 
					Requires:       libosmo-mgcp-client9 = %{version}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%description -n libosmo-mgcp-client-devel
 | 
				
			||||||
 | 
					Osmocom's Media Gateway Control Protocol client librarary.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This subpackage contains libraries and header files for developing
 | 
				
			||||||
 | 
					applications that want to make use of libosmo-mgcp-client.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%package -n libosmo-mgcp-devel
 | 
				
			||||||
 | 
					Summary:        Development files for Osmocom's Media Gateway server library
 | 
				
			||||||
 | 
					Group:          Development/Libraries/C and C++
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%description -n libosmo-mgcp-devel
 | 
				
			||||||
 | 
					Osmocom's Media Gateway Control Protocol server library.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This subpackage contains libraries and header files for developing
 | 
				
			||||||
 | 
					applications that want to make use of libosmo-mgcp.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%prep
 | 
				
			||||||
 | 
					%setup -q
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%build
 | 
				
			||||||
 | 
					echo "%{version}" >.tarball-version
 | 
				
			||||||
 | 
					autoreconf -fi
 | 
				
			||||||
 | 
					%configure \
 | 
				
			||||||
 | 
					  --disable-static \
 | 
				
			||||||
 | 
					  --docdir=%{_docdir}/%{name} \
 | 
				
			||||||
 | 
					  --with-systemdsystemunitdir=%{_unitdir}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					make %{?_smp_mflags}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%install
 | 
				
			||||||
 | 
					%make_install
 | 
				
			||||||
 | 
					find %{buildroot} -type f -name "*.la" -delete -print
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%check
 | 
				
			||||||
 | 
					make %{?_smp_mflags} check || (find . -name testsuite.log -exec cat {} +)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%post   -n libosmo-mgcp-client9 -p /sbin/ldconfig
 | 
				
			||||||
 | 
					%postun -n libosmo-mgcp-client9 -p /sbin/ldconfig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%if 0%{?suse_version}
 | 
				
			||||||
 | 
					%preun
 | 
				
			||||||
 | 
					%service_del_preun osmo-mgw.service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%postun
 | 
				
			||||||
 | 
					%service_del_postun osmo-mgw.service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%pre
 | 
				
			||||||
 | 
					%service_add_pre osmo-mgw.service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%post
 | 
				
			||||||
 | 
					%service_add_post osmo-mgw.service
 | 
				
			||||||
 | 
					%endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%files
 | 
				
			||||||
 | 
					%license COPYING
 | 
				
			||||||
 | 
					%doc AUTHORS README
 | 
				
			||||||
 | 
					%dir %{_docdir}/%{name}/examples
 | 
				
			||||||
 | 
					%dir %{_docdir}/%{name}/examples/osmo-mgw
 | 
				
			||||||
 | 
					%{_docdir}/%{name}/examples/osmo-mgw/osmo-mgw.cfg
 | 
				
			||||||
 | 
					%{_docdir}/%{name}/examples/osmo-mgw/osmo-mgw-abis_e1.cfg
 | 
				
			||||||
 | 
					%{_bindir}/osmo-mgw
 | 
				
			||||||
 | 
					%{_unitdir}/osmo-mgw.service
 | 
				
			||||||
 | 
					%dir %{_sysconfdir}/osmocom
 | 
				
			||||||
 | 
					%config(noreplace) %{_sysconfdir}/osmocom/osmo-mgw.cfg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%files -n libosmo-mgcp-client9
 | 
				
			||||||
 | 
					%{_libdir}/libosmo-mgcp-client.so.9*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%files -n libosmo-mgcp-client-devel
 | 
				
			||||||
 | 
					%{_libdir}/libosmo-mgcp-client.so
 | 
				
			||||||
 | 
					%{_libdir}/pkgconfig/libosmo-mgcp-client.pc
 | 
				
			||||||
 | 
					%dir %{_includedir}/osmocom
 | 
				
			||||||
 | 
					%dir %{_includedir}/osmocom/mgcp_client
 | 
				
			||||||
 | 
					%{_includedir}/osmocom/mgcp_client/*.h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%files -n libosmo-mgcp-devel
 | 
				
			||||||
 | 
					%dir %{_includedir}/osmocom
 | 
				
			||||||
 | 
					%dir %{_includedir}/osmocom/mgcp
 | 
				
			||||||
 | 
					%{_includedir}/osmocom/mgcp/*.h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%changelog
 | 
				
			||||||
							
								
								
									
										6
									
								
								contrib/systemd/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								contrib/systemd/Makefile.am
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					EXTRA_DIST = osmo-mgw.service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if HAVE_SYSTEMD
 | 
				
			||||||
 | 
					systemdsystemunit_DATA = \
 | 
				
			||||||
 | 
					  osmo-mgw.service
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
@@ -1,11 +0,0 @@
 | 
				
			|||||||
[Unit]
 | 
					 | 
				
			||||||
Description=OpenBSC MGCP
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[Service]
 | 
					 | 
				
			||||||
Type=simple
 | 
					 | 
				
			||||||
Restart=always
 | 
					 | 
				
			||||||
ExecStart=/usr/bin/osmo-bsc_mgcp -s -c /etc/osmocom/osmo-bsc-mgcp.cfg
 | 
					 | 
				
			||||||
RestartSec=2
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[Install]
 | 
					 | 
				
			||||||
WantedBy=multi-user.target
 | 
					 | 
				
			||||||
							
								
								
									
										13
									
								
								contrib/systemd/osmo-mgw.service
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								contrib/systemd/osmo-mgw.service
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					[Unit]
 | 
				
			||||||
 | 
					Description=Osmocom Media Gateway (MGW)
 | 
				
			||||||
 | 
					After=network-online.target
 | 
				
			||||||
 | 
					Wants=network-online.target
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[Service]
 | 
				
			||||||
 | 
					Type=simple
 | 
				
			||||||
 | 
					Restart=always
 | 
				
			||||||
 | 
					ExecStart=/usr/bin/osmo-mgw -s -c /etc/osmocom/osmo-mgw.cfg
 | 
				
			||||||
 | 
					RestartSec=2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[Install]
 | 
				
			||||||
 | 
					WantedBy=multi-user.target
 | 
				
			||||||
							
								
								
									
										721
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										721
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							@@ -1,3 +1,724 @@
 | 
				
			|||||||
 | 
					osmo-mgw (1.9.2) unstable; urgency=medium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * systemd: depend on networking-online.target
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Oliver Smith <osmith@sysmocom.de>  Fri, 26 May 2023 14:57:36 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-mgw (1.9.1) unstable; urgency=medium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Vadim Yanitskiy ]
 | 
				
			||||||
 | 
					  * libosmo-mgcp: e1: fix memleaks in e1_recv_cb()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Harald Welte <laforge@osmocom.org>  Mon, 18 Apr 2022 10:58:50 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-mgw (1.9.0) unstable; urgency=medium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Harald Welte ]
 | 
				
			||||||
 | 
					  * TOS bits != DSCP
 | 
				
			||||||
 | 
					  * manual: don't define fig-bsc twice
 | 
				
			||||||
 | 
					  * switch from osmo_sock_set_dscp() to OSMO_SOCK_F_DSCP()
 | 
				
			||||||
 | 
					  * mgw: Add support for setting socket priority from VTY
 | 
				
			||||||
 | 
					  * manual: Include QoS chapter and add osmo-mgw specific example
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Keith ]
 | 
				
			||||||
 | 
					  * Add vty command 'show mgcp active'
 | 
				
			||||||
 | 
					  * Log some useful messages at ERROR/INFO instead of DEBUG
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Neels Hofmeyr ]
 | 
				
			||||||
 | 
					  * send DLCX only once
 | 
				
			||||||
 | 
					  * tweak termination DLCX log msg
 | 
				
			||||||
 | 
					  * add osmo_mgcpc_ep_ci_get_remote_rtp_info()
 | 
				
			||||||
 | 
					  * check_rtp_destin(): clarify log msg
 | 
				
			||||||
 | 
					  * mgcp_client_fsm delete: set mgcp_client as ctx, not NULL
 | 
				
			||||||
 | 
					  * mgcp_client_endpoint_fsm: on term, still let conns wait for DLCX OK
 | 
				
			||||||
 | 
					  * mgcp_client_fsm: add missing log_subsys
 | 
				
			||||||
 | 
					  * mgcp_client: add logging on received MGCP messages
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Philipp Maier ]
 | 
				
			||||||
 | 
					  * mgcp_network: fix implicit address loopback
 | 
				
			||||||
 | 
					  * mgcp_common, mgcp_udp_send: make parameter buf const
 | 
				
			||||||
 | 
					  * mgcp_network: refactor MGCP_DUMMY_LOAD
 | 
				
			||||||
 | 
					  * mgcp_client: drop nunnecessary else statement
 | 
				
			||||||
 | 
					  * mgcp_client: fix error handling in mgcp message generation
 | 
				
			||||||
 | 
					  * mgcp_protocol: fix loop that sends dummy RTP packets
 | 
				
			||||||
 | 
					  * mgw_main: fix loop that resets all endpoints
 | 
				
			||||||
 | 
					  * mgcp_trunk: drop ws line
 | 
				
			||||||
 | 
					  * mgcp_ratectr: drop ws line
 | 
				
			||||||
 | 
					  * mgcp_ratectr: fix sourcecode formatting
 | 
				
			||||||
 | 
					  * mgcp_trunk: add value string for trunk type.
 | 
				
			||||||
 | 
					  * mgcp_ratectr: refactor rate counter and set group name
 | 
				
			||||||
 | 
					  * mgcp_protocol: forward declare mgcp_endpoint
 | 
				
			||||||
 | 
					  * mgcp_endp: make wildcarded detection separate
 | 
				
			||||||
 | 
					  * mgcp_protocol: refactor request handler array
 | 
				
			||||||
 | 
					  * mgcp_trunk: use unsigned int instead of int as trunk_nr
 | 
				
			||||||
 | 
					  * mgcp_protocol: refactor MGCP request handling
 | 
				
			||||||
 | 
					  * mgcp_ratectr: add stats items to monitor trunk usage
 | 
				
			||||||
 | 
					  * mgcp_msg: add trunk parameter to mgcp_check_param for logging
 | 
				
			||||||
 | 
					  * mgcp_protocol: refactor function create_response_with_sdp
 | 
				
			||||||
 | 
					  * mgcp_protocol: add support for wildcarded DLCX
 | 
				
			||||||
 | 
					  * remove struct member wildcarded_req from struct mgcp_endpoint
 | 
				
			||||||
 | 
					  * mgcp_lient: remove unsubstantial FIXME note
 | 
				
			||||||
 | 
					  * mgcp_protocol: assert endp when it becomes mandatory
 | 
				
			||||||
 | 
					  * mgcp_trunk: check MGW domain name earlier
 | 
				
			||||||
 | 
					  * mgcp_ratectr: add stats items to monitor trunk usage
 | 
				
			||||||
 | 
					  * mgcp_client: fix typo Initalize -> Initialize
 | 
				
			||||||
 | 
					  * mgcp_protocol: get rid of policy_cb and change_cb
 | 
				
			||||||
 | 
					  * mgcp_ratectr: do not set talloc destructor on library allocated item
 | 
				
			||||||
 | 
					  * mgcp_client: allow to reset endpoints on startup
 | 
				
			||||||
 | 
					  * mgcp_client_vty: remove unnecessary checks
 | 
				
			||||||
 | 
					  * mgcp_client: do not print (null) when address is ANY
 | 
				
			||||||
 | 
					  * mgcp_client: refactor function init_socket
 | 
				
			||||||
 | 
					  * libosmo-mgcp-client: extend the mgcp_client for MGW pooling
 | 
				
			||||||
 | 
					  * mgcp_client_vty: add missing docstrings
 | 
				
			||||||
 | 
					  * mgcp_client_vty: add OSMO_ASSERT on pool parameter
 | 
				
			||||||
 | 
					  * mgcp_client_vty: fix docstrings for mgw-pool
 | 
				
			||||||
 | 
					  * mgcp_client_vty: cosmetic: doc string should terminated with \n
 | 
				
			||||||
 | 
					  * mgcp_client_vty: fixing docstring
 | 
				
			||||||
 | 
					  * mgcp_ratectr: remove unusued rate counters
 | 
				
			||||||
 | 
					  * mgcp_client: fix typo in doxygen comment
 | 
				
			||||||
 | 
					  * mgcp_client: add MGW name as logging context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Pau Espin Pedrol ]
 | 
				
			||||||
 | 
					  * Use new stat item/ctr getter APIs
 | 
				
			||||||
 | 
					  * constify arg in addr_is_any()
 | 
				
			||||||
 | 
					  * Define patch_ssrc as bool type
 | 
				
			||||||
 | 
					  * constify some function arg pointers
 | 
				
			||||||
 | 
					  * mgcp_network.c: Reorder some functions in file
 | 
				
			||||||
 | 
					  * mgcp_send_dummy: Check RTP destination is available before attempt tx
 | 
				
			||||||
 | 
					  * mgw: rx CRCX: Avoid sending dummy rtp if remote address not provided
 | 
				
			||||||
 | 
					  * Fail rx MDCX sendrecv with invalid remote addr
 | 
				
			||||||
 | 
					  * Take into account Marker bit when patching RTP stream
 | 
				
			||||||
 | 
					  * Use DLMGCP instead of DLGLOBAL in log lines
 | 
				
			||||||
 | 
					  * Fix attribute parsing on gcc 11.1.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ neels ]
 | 
				
			||||||
 | 
					  * Revert "mgcp_ratectr: add stats items to monitor trunk usage"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Daniel Willmann ]
 | 
				
			||||||
 | 
					  * contrib/jenkins: Use ASAN for osmo-mgw
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Oliver Smith ]
 | 
				
			||||||
 | 
					  * mgcp_client_vty: add missing NO_STR
 | 
				
			||||||
 | 
					  * Revert "Turn some compiler warnings into errors"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Eric ]
 | 
				
			||||||
 | 
					  * add vscode stuff to gitignore
 | 
				
			||||||
 | 
					  * configure.ac: fix maybe-uninitialized for clang
 | 
				
			||||||
 | 
					  * fix missing includes and forward declarations
 | 
				
			||||||
 | 
					  * rename do_retransmission
 | 
				
			||||||
 | 
					  * mgcp_sdp: fix potential leak
 | 
				
			||||||
 | 
					  * stats: make sanitizers happy
 | 
				
			||||||
 | 
					  * libosmo-mgcp: cleanup audio codex alloc
 | 
				
			||||||
 | 
					  * libosmo-mgcp: atomic rate counter group indexes
 | 
				
			||||||
 | 
					  * libosmo-mgcp: do not use the default msgb talloc context
 | 
				
			||||||
 | 
					  * globally lock the portrange when trying to grab a port to prep for multithreading
 | 
				
			||||||
 | 
					  * embed strings into structs
 | 
				
			||||||
 | 
					  * adjust talloc context
 | 
				
			||||||
 | 
					  * endp: do not cache cfg pointer
 | 
				
			||||||
 | 
					  * add modified .clang-format
 | 
				
			||||||
 | 
					  * rename strip_epname and find_specific_endpoint and make them available
 | 
				
			||||||
 | 
					  * fix mgcp_conn_free_all
 | 
				
			||||||
 | 
					  * fix up some docstrings that lost their dot
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Vadim Yanitskiy ]
 | 
				
			||||||
 | 
					  * libosmo-mgcp: use OSMO_STRLCPY_ARRAY in mgcp_codec_add()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Pau Espin Pedrol <pespin@sysmocom.de>  Tue, 16 Nov 2021 16:59:21 +0100
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-mgw (1.8.1) unstable; urgency=medium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * attempt to fix RPM spec file after recent soversion bump
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Harald Welte <laforge@osmocom.org>  Wed, 24 Feb 2021 10:56:17 +0100
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-mgw (1.8.0) unstable; urgency=medium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Harald Welte ]
 | 
				
			||||||
 | 
					  * Fix number of endpoints of default trunk
 | 
				
			||||||
 | 
					  * Add CTRL interface to osmo-mgw
 | 
				
			||||||
 | 
					  * Update per-trunk global packet/byte counters in real-time
 | 
				
			||||||
 | 
					  * remove accidential TODO-RELEASE entry
 | 
				
			||||||
 | 
					  * mgcp_protocol: Avoid code duplication between virtual + other trunks
 | 
				
			||||||
 | 
					  * osmo-mgw.spec.in: Use %config(noreplace) to retain current config file
 | 
				
			||||||
 | 
					  * mgcp_client_init(): consider "talloc returns NULL" case
 | 
				
			||||||
 | 
					  * mgcp_client_pending_add(): Consider "talloc returns NULL" case
 | 
				
			||||||
 | 
					  * libosmo-mgcp-client: fix memleak in case if no response is received
 | 
				
			||||||
 | 
					  * debian/control + SPEC: Add missing build dependency to libosmo-abis
 | 
				
			||||||
 | 
					  * osmo-mgw.spec.in: Fix dependency to libosmoabis
 | 
				
			||||||
 | 
					  * osmo-mgw.spec.in: Add missing dependency to libosmotrau
 | 
				
			||||||
 | 
					  * Add example osmo-mgw configuration file for Abis/E1
 | 
				
			||||||
 | 
					  * use osmo_fd_setup() whenever applicable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Neels Hofmeyr ]
 | 
				
			||||||
 | 
					  * fix vty dump_trunk: start from zero, do not omit first CONN
 | 
				
			||||||
 | 
					  * allow larger MGCP client wqueue: 10 -> 1024
 | 
				
			||||||
 | 
					  * add osmo-mgw --vty-ref-xml: dump VTY ref XML to stdout
 | 
				
			||||||
 | 
					  * manuals: generate vty reference xml at build time
 | 
				
			||||||
 | 
					  * refactor: use msgb to receive, pass and send RTP packets
 | 
				
			||||||
 | 
					  * change timer T2427001 to X2427
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Philipp Maier ]
 | 
				
			||||||
 | 
					  * doc: do not bind osmo-mgw to random ip-address
 | 
				
			||||||
 | 
					  * cosmetic: remove excess newlines
 | 
				
			||||||
 | 
					  * mgcp: remove unused callback pointer
 | 
				
			||||||
 | 
					  * mgcp: find better locations for LOGPCONN and LOGPENDP
 | 
				
			||||||
 | 
					  * vty: fix unreachable code (error msg on trunk alloc fail)
 | 
				
			||||||
 | 
					  * mgcp_vty: fix indentation
 | 
				
			||||||
 | 
					  * osmo-mgw: rename struct mgcp_trunk_config and symbol tcfg
 | 
				
			||||||
 | 
					  * mgcp_vty: fix indentation in VTY config write
 | 
				
			||||||
 | 
					  * osmo-mgw: refactor endpoint and trunk handling
 | 
				
			||||||
 | 
					  * mgcp_trunk: remove audio_name and audio_payload
 | 
				
			||||||
 | 
					  * ratectr: move rate counter definitions into mgcp_ratectr.h
 | 
				
			||||||
 | 
					  * cosmetic: fix doxygen
 | 
				
			||||||
 | 
					  * cosmetic: fix doxygen
 | 
				
			||||||
 | 
					  * cosmetic: fix doxygen for mgcp_cleanup_rtp_bridge_cb()
 | 
				
			||||||
 | 
					  * trunk: get rid of virt_trunk pointer
 | 
				
			||||||
 | 
					  * cosmetic: remove excess space
 | 
				
			||||||
 | 
					  * endp: move endpoint name generation into mgcp_endp.c
 | 
				
			||||||
 | 
					  * endp: add name generator function for E1 endpoints
 | 
				
			||||||
 | 
					  * mgcp_client: add docstring for mgcp_client_rtpbridge_wildcard()
 | 
				
			||||||
 | 
					  * mgcp_trunk: fix docstring for mgcp_trunk_alloc()
 | 
				
			||||||
 | 
					  * mgcp_osmux: remove unused define constants
 | 
				
			||||||
 | 
					  * mgcp_trunk: move enum mgcp_trunk_type to mgcp_trunk.h
 | 
				
			||||||
 | 
					  * mgcp_trunk: use enum type for trunk type variable
 | 
				
			||||||
 | 
					  * trunk: parse E1 trunk number
 | 
				
			||||||
 | 
					  * endp: add typeset for e1-endpoints
 | 
				
			||||||
 | 
					  * mgcp_conn: move struct mgcp_conn mgcp_conn.h
 | 
				
			||||||
 | 
					  * mgcp_internal: remove forward declaration struct mgcp_endpoint_type
 | 
				
			||||||
 | 
					  * endp: add E1 endpoint interlocking
 | 
				
			||||||
 | 
					  * endp: require domain name also for E1 endpoints
 | 
				
			||||||
 | 
					  * mgcp_trunk: pick trunk by number and type
 | 
				
			||||||
 | 
					  * mgcp_client: add function to generate e1-endpoint names
 | 
				
			||||||
 | 
					  * mgcp_endp: use define constant to define max number of E1 subslots
 | 
				
			||||||
 | 
					  * mgcp_endp.c: cosmetic: fix sourcecode formatting
 | 
				
			||||||
 | 
					  * mgcp_trunk: remove double check
 | 
				
			||||||
 | 
					  * mgcp_test: do not access endpoint array elements directly
 | 
				
			||||||
 | 
					  * mgcp_vty: fix endpoint number configuration
 | 
				
			||||||
 | 
					  * mgcp_test: remove trunk2 from unit-test
 | 
				
			||||||
 | 
					  * mgcp_trunk: use talloc_zero_array instead of _talloc_zero_array
 | 
				
			||||||
 | 
					  * mgcp_protocol: remove unused variable
 | 
				
			||||||
 | 
					  * mgcp_e1: finish E1 support, add E1 support from libosmoabis
 | 
				
			||||||
 | 
					  * get rid of mgcp_internal.h
 | 
				
			||||||
 | 
					  * mgcp_ratectr: fix comments in header file
 | 
				
			||||||
 | 
					  * mgcp_e1: use return value of e1inp_line_update()
 | 
				
			||||||
 | 
					  * mgcp_protocol: log when endpoint is unavailable
 | 
				
			||||||
 | 
					  * cosmetic: add missing new-line
 | 
				
			||||||
 | 
					  * mgcp_trunk: drop "trunk 0" limitation
 | 
				
			||||||
 | 
					  * mgcp_e1: make E1 ts initalization more debugable
 | 
				
			||||||
 | 
					  * mgcp_e1: remove unused struct member trunk->e1.line
 | 
				
			||||||
 | 
					  * mgcp_endp: use NUM_E1_TS from e1_input.h
 | 
				
			||||||
 | 
					  * mgcp_trunk: increase default number of virtual endpoints
 | 
				
			||||||
 | 
					  * cosmetic: mgcp_client_fsm: change error message.
 | 
				
			||||||
 | 
					  * mgcp_vty: remove remains of loopback functionality
 | 
				
			||||||
 | 
					  * mgcp_vty: deprecate bind early command
 | 
				
			||||||
 | 
					  * mgcp_e1: do not expose function  mgcp_e1_init()
 | 
				
			||||||
 | 
					  * mgcp_vty: add user attributes to configuration commands
 | 
				
			||||||
 | 
					  * overview: update section limitations.
 | 
				
			||||||
 | 
					  * overview: fix graph "OsmoMGW used with OsmoBSC"
 | 
				
			||||||
 | 
					  * overview: fix graph "OsmoMGW used with OsmoMSC"
 | 
				
			||||||
 | 
					  * overview: add graph to show E1 integration
 | 
				
			||||||
 | 
					  * configuration: remove hint towards trunk 0 limit
 | 
				
			||||||
 | 
					  * configuration: drop note about lackin E1 support
 | 
				
			||||||
 | 
					  * configuration: add note that changes to trunks need a restart
 | 
				
			||||||
 | 
					  * mgcp_vty: fix config write for trunk 0
 | 
				
			||||||
 | 
					  * mgcp_vty: add missing VTY commands for E1 trunks
 | 
				
			||||||
 | 
					  * mgcp_trunk: get rid of magic numbers for E1 slots
 | 
				
			||||||
 | 
					  * configuration: add section about E1 trunks
 | 
				
			||||||
 | 
					  * usermanual: add chapter about mgcp endpoints
 | 
				
			||||||
 | 
					  * mgcp_client: get rid of magic numbers for E1 slots
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Eric ]
 | 
				
			||||||
 | 
					  * tests: dlopen does not imply availability of dlsym..
 | 
				
			||||||
 | 
					  * configure.ac: fix libtool issue with clang and sanitizer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Alexander Chemeris ]
 | 
				
			||||||
 | 
					  * vty: Prepend VTY output of counters for better visual separation.
 | 
				
			||||||
 | 
					  * counters: Implement more useful counters.
 | 
				
			||||||
 | 
					  * mgcp_network: Fix a typo in the comment bahviour -> behaviour
 | 
				
			||||||
 | 
					  * rtp_bridge: Demote a chatty ERROR log message to DEBUG level.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Pau Espin Pedrol ]
 | 
				
			||||||
 | 
					  * Use OSMO_FD_* instead of deprecated BSC_FD_*
 | 
				
			||||||
 | 
					  * Support setting rt-prio and cpu-affinity mask through VTY
 | 
				
			||||||
 | 
					  * cosmetic: Rename main talloc ctx
 | 
				
			||||||
 | 
					  * mgcp-client: Support IPv6 in osmo_mgcpc_ep_ci_get_crcx_info_to_sockaddr() implementation
 | 
				
			||||||
 | 
					  * mgcp-client: Fix trailing whitespace in mgcp_client_fsm.h
 | 
				
			||||||
 | 
					  * mgcp_client: Use INET6_ADDRSTRLEN to store addresses in str format
 | 
				
			||||||
 | 
					  * mgcp_client: Allow submitting and parsing IPv6 addr in SDP
 | 
				
			||||||
 | 
					  * mgcp_client: Allow setting IPv6 addresses
 | 
				
			||||||
 | 
					  * mgcp_client: Make MGCP_CLIENT_LOCAL_ADDR_DEFAULT IPv6 compatible
 | 
				
			||||||
 | 
					  * mgcp_client: Support validating IPv6 addresses in CRCX and MDCX commands
 | 
				
			||||||
 | 
					  * mgcp_client: Deprecate unused IPv4-only API
 | 
				
			||||||
 | 
					  * mgcp_client: copy back Connection Information from MDCX ACK
 | 
				
			||||||
 | 
					  * mgw: Fix mgcp_rtp_end field description comment
 | 
				
			||||||
 | 
					  * mgw: Initial IPv6 support
 | 
				
			||||||
 | 
					  * mgw: Introduce VTY cmd 'rtp bind-ip-v6' command
 | 
				
			||||||
 | 
					  * mgw: Find and store RTP conn local_addr once during CRCX handling
 | 
				
			||||||
 | 
					  * mgw: Announce and rebind new local address if change required during MDCX
 | 
				
			||||||
 | 
					  * mgw: osmux: Avoid sending packets on recvonly connection
 | 
				
			||||||
 | 
					  * mgw: Release endpoint after last conn times out
 | 
				
			||||||
 | 
					  * mgw: osmux: Fix conn watchdog timeout not updated
 | 
				
			||||||
 | 
					  * mgw: Don't be case-sensitive when parsing X-Osmo-IGN param
 | 
				
			||||||
 | 
					  * cosmetic: Fix typo in comment
 | 
				
			||||||
 | 
					  * mgw: Avoid logging notice message each time we receive nt param in LCO
 | 
				
			||||||
 | 
					  * mgw: Fix return value documentation for API mgcp_verify_call_id
 | 
				
			||||||
 | 
					  * cosmetic: Fix typo in comment
 | 
				
			||||||
 | 
					  * contrib/jenkins: Enable parallel make in make distcheck
 | 
				
			||||||
 | 
					  * .gitignore: Ignore new autofoo tmp files
 | 
				
			||||||
 | 
					  * tests: Replace deprecated API log_set_print_filename
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Oliver Smith ]
 | 
				
			||||||
 | 
					  * contrib: import RPM spec
 | 
				
			||||||
 | 
					  * contrib: integrate RPM spec
 | 
				
			||||||
 | 
					  * Makefile.am: EXTRA_DIST: debian, contrib/*.spec.in
 | 
				
			||||||
 | 
					  * contrib/jenkins: don't build osmo-gsm-manuals
 | 
				
			||||||
 | 
					  * configure.ac: set -std=gnu11
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Vadim Yanitskiy ]
 | 
				
			||||||
 | 
					  * libosmo-mgcp-client: fix use-after-free in mgcp_client_tx()
 | 
				
			||||||
 | 
					  * libosmo-mgcp-client: fix use-after-free in mgcp_msg_gen()
 | 
				
			||||||
 | 
					  * libosmo-mgcp: fix unsigned compared against 0 in mgcp_trunk_by_name()
 | 
				
			||||||
 | 
					  * libosmo-mgcp: fix unused extra argument to printf() in add_fmtp()
 | 
				
			||||||
 | 
					  * libosmo-mgcp: always check result of msgb_printf() in add_fmtp()
 | 
				
			||||||
 | 
					  * libosmo-mgcp-client: mgcp_client_tx(): return rc on error
 | 
				
			||||||
 | 
					  * debian/control: change maintainer to the Osmocom team / mailing list
 | 
				
			||||||
 | 
					  * vty: use install_lib_element() and install_lib_element_ve()
 | 
				
			||||||
 | 
					  * main: add --vty-ref-mode, use vty_dump_xml_ref_mode()
 | 
				
			||||||
 | 
					  * fixup mgcp_trunk: increase default number of virtual endpoints
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Alexander Couzens ]
 | 
				
			||||||
 | 
					  * configure.ac: require libosmoabis + libosmotrau >= 1.0.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Pau Espin Pedrol <pespin@sysmocom.de>  Tue, 23 Feb 2021 18:28:45 +0100
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-mgw (1.7.0) unstable; urgency=medium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Neels Hofmeyr ]
 | 
				
			||||||
 | 
					  * rename codecs_cmp() to codecs_same()
 | 
				
			||||||
 | 
					  * mgcp_codec: constify 'param' arg
 | 
				
			||||||
 | 
					  * fix crashes: don't assert on incoming RTP packet size
 | 
				
			||||||
 | 
					  * mgcp_send(): stop looping on conversion error
 | 
				
			||||||
 | 
					  * mgcp_codec: split codec_free() off of codec_init()
 | 
				
			||||||
 | 
					  * fix memleak: actually free strings in mgcp_codec_reset_all()
 | 
				
			||||||
 | 
					  * mgcp_test: extend / rewrite test_mgcp_codec_pt_translate()
 | 
				
			||||||
 | 
					  * test_mgcp_codec_pt_translate(): more tests
 | 
				
			||||||
 | 
					  * differentiate AMR octet-aligned=0 vs =1
 | 
				
			||||||
 | 
					  * ptmap: implicitly match  '/8000' and '/8000/1'
 | 
				
			||||||
 | 
					  * mgcp_codec: codec_set(): log about all possible errors
 | 
				
			||||||
 | 
					  * mgcp_codec_add: fix audio_name size check
 | 
				
			||||||
 | 
					  * explicitly free codecs in mgcp_rtp_conn_cleanup()
 | 
				
			||||||
 | 
					  * tweak mgcp_parse_audio_ptime_rtpmap()
 | 
				
			||||||
 | 
					  * SDP: store all ptmap entries
 | 
				
			||||||
 | 
					  * mgcp_client_fsm cleanup: Do not assert on DLCX failure
 | 
				
			||||||
 | 
					  * clear pending requests on MGCP failure
 | 
				
			||||||
 | 
					  * client: endp fsm: add notify struct, prep for cancel-notify
 | 
				
			||||||
 | 
					  * client: endp fsm: clear ci[] before dispatching DLCX success
 | 
				
			||||||
 | 
					  * client: endp fsm: allow cancelling a notify event
 | 
				
			||||||
 | 
					  * client: endp fsm: add osmo_mgcpc_ep_ci_ep()
 | 
				
			||||||
 | 
					  * accept MGCP without SDP
 | 
				
			||||||
 | 
					  * fix use-after-free: require new fsm deferred dealloc, check for term
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Pau Espin Pedrol ]
 | 
				
			||||||
 | 
					  * mgcp_test: Correctly release all endpoints allocated
 | 
				
			||||||
 | 
					  * mgw: Allocate mgcp_conn instance under tcfg->endpoints
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Harald Welte ]
 | 
				
			||||||
 | 
					  * manual: Fix copy+paste error
 | 
				
			||||||
 | 
					  * mgcp_client: Check for osmo_fsm_register() error return value
 | 
				
			||||||
 | 
					  * Move fsm_mgcp_client regstration to __attribute__((contructor))
 | 
				
			||||||
 | 
					  * exit(2) on unsupported positional arguments on command line
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Oliver Smith ]
 | 
				
			||||||
 | 
					  * osmoappdesc.py: switch to python 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Pau Espin Pedrol <pespin@sysmocom.de>  Fri, 03 Jan 2020 13:35:09 +0100
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-mgw (1.6.0) unstable; urgency=medium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Oliver Smith ]
 | 
				
			||||||
 | 
					  * Cosmetic: fix spaces/tabs in mgcp_requests[]
 | 
				
			||||||
 | 
					  * Inactive connection cleanup (disabled by default)
 | 
				
			||||||
 | 
					  * debian: create -doc subpackage with pdf manuals
 | 
				
			||||||
 | 
					  * vty: allow 0 as conn-timeout to disable it
 | 
				
			||||||
 | 
					  * vty: update desc of conn-timeout
 | 
				
			||||||
 | 
					  * manuals: update VTY documentation
 | 
				
			||||||
 | 
					  * "make dist" fix for: no rule to make mgcp_common.h
 | 
				
			||||||
 | 
					  * contrib/jenkins.sh: run "make maintainer-clean"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Philipp Maier ]
 | 
				
			||||||
 | 
					  * Add option to GSM HR frames to RFC5593 representation
 | 
				
			||||||
 | 
					  * mgcp_sdp: cosmetic: correct typo in comment
 | 
				
			||||||
 | 
					  * mgco_client: cosmetic: remove excess whitespace
 | 
				
			||||||
 | 
					  * mgcp_sdp: mgcp_sdp.c does not include own header file
 | 
				
			||||||
 | 
					  * mgcp_sdp: untangle parsing of a= parameters
 | 
				
			||||||
 | 
					  * mgcp_network: use mgcp_rtp_codec in downlink format callback
 | 
				
			||||||
 | 
					  * AMR: Add function to convert between bw-effient and octet aligned mode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Neels Hofmeyr ]
 | 
				
			||||||
 | 
					  * log: don't spam with "can not patch PT" messages
 | 
				
			||||||
 | 
					  * mgcp client: allow setting conn mode for CRCX and MDCX
 | 
				
			||||||
 | 
					  * make codec_table public as osmo_mgcpc_codec_names
 | 
				
			||||||
 | 
					  * move MGW endpoint FSM from osmo-bsc to here
 | 
				
			||||||
 | 
					  * fix: multiple initial CRCX
 | 
				
			||||||
 | 
					  * constify map_codec_to_pt() ptmap arg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Pau Espin Pedrol ]
 | 
				
			||||||
 | 
					  * mgcp-client: whitespace cleanup in mgcp_client.c
 | 
				
			||||||
 | 
					  * mgcp-client: Sanitize implementation of mgcp_client_rtpbridge_wildcard
 | 
				
			||||||
 | 
					  * libosmo-mgcp: Use trunk type during endpoint allocation
 | 
				
			||||||
 | 
					  * cosmetic: Fix typos in comment
 | 
				
			||||||
 | 
					  * cosmetic: tests: mgcp_client_test: clean trailing whitespace
 | 
				
			||||||
 | 
					  * mgcp_msg: Log faulty line on Osmux parsing error
 | 
				
			||||||
 | 
					  * cosmetic: handle_modify_con: Fix indentation level
 | 
				
			||||||
 | 
					  * Introduce log fmt helpers LOGPENDP and LOGPCONN
 | 
				
			||||||
 | 
					  * create_response_with_sdp: Fix inclusion of X-Osmux
 | 
				
			||||||
 | 
					  * osmux: Cleanup of CID alloc pool APIs
 | 
				
			||||||
 | 
					  * mgcp_osmux.c: osmux_enable_endpoint: Fix incorrect return check
 | 
				
			||||||
 | 
					  * osmux: Log osmux socket during osmux_init
 | 
				
			||||||
 | 
					  * mgcp-cli: Change osmo_mgcpc_ep_fsm name to avoid collision with old osmo-bsc
 | 
				
			||||||
 | 
					  * osmux: Document func and return different rc upon osmux init failure
 | 
				
			||||||
 | 
					  * osmux: Fix reception of legacy dummy payloads
 | 
				
			||||||
 | 
					  * osmux: Use LOGPCONN in several log calls
 | 
				
			||||||
 | 
					  * cosmetic: mgcp_udp_send: Document port param is in network byte order
 | 
				
			||||||
 | 
					  * cosmetic: osmux: Document network byte order in port variable
 | 
				
			||||||
 | 
					  * vty: Allow enabling Osmux
 | 
				
			||||||
 | 
					  * osmux: Allocate CID during CRCX
 | 
				
			||||||
 | 
					  * osmux: Introduce mgcp_conn_rtp_is_osmux() helper
 | 
				
			||||||
 | 
					  * osmux: Mark conn_rtp->type as osmux during CRCX
 | 
				
			||||||
 | 
					  * mgcp-cli: Allow submitting X-Osmux on CRCX request
 | 
				
			||||||
 | 
					  * mgcp-cli: Parse X-Osmux on CRCX response
 | 
				
			||||||
 | 
					  * osmux: Handle Osmux MGCP extension in MDCX messages
 | 
				
			||||||
 | 
					  * mgcp-cli: Allow submitting X-Osmux on MDCX request
 | 
				
			||||||
 | 
					  * mgcp-cli: Parse X-Osmux on MDCX response
 | 
				
			||||||
 | 
					  * osmux: Drop unneeded OSMUX_STATE_NEGOTIATING
 | 
				
			||||||
 | 
					  * mgcp-cli: endpoint_fsm: Add API to retrieve Osmux CID from MGW
 | 
				
			||||||
 | 
					  * osmux: Provide correct local port during mgcp resp
 | 
				
			||||||
 | 
					  * osmux: Use remote port to send osmux frames
 | 
				
			||||||
 | 
					  * osmux: Improve logging around osmux enabling events
 | 
				
			||||||
 | 
					  * osmux: Delay osmux enable of conn until remote addr is configured by MDCX
 | 
				
			||||||
 | 
					  * osmux: Redo read/write osmux glue code to have data routed correctly
 | 
				
			||||||
 | 
					  * mgw, mgcp-li: Handle X-Osmux param name as case insensitive
 | 
				
			||||||
 | 
					  * osmux: Use DUMMY ft msg as per Osmux spec
 | 
				
			||||||
 | 
					  * osmux: Fix loopback for Osmux connections
 | 
				
			||||||
 | 
					  * osmux: Fix CID release for non-enabled connections
 | 
				
			||||||
 | 
					  * osmux: Fix hardcoded rtp payload_type 98 in osmux conn
 | 
				
			||||||
 | 
					  * mgcp-cli: Validate osmux cid value during mgcp_msg_gen
 | 
				
			||||||
 | 
					  * mgw: Support uppercase LCO options
 | 
				
			||||||
 | 
					  * mgw: Support lowercase header parameters
 | 
				
			||||||
 | 
					  * mgcp-cli: Support lowercase header parameters
 | 
				
			||||||
 | 
					  * mgw: Support receiving uppercase connection mode
 | 
				
			||||||
 | 
					  * mgw: Support receiving lowercase LCO codec
 | 
				
			||||||
 | 
					  * mgw: Make check of duplicated LCO fields case insensitive
 | 
				
			||||||
 | 
					  * mgw: Allow receiving lowercase MGCP header keyword
 | 
				
			||||||
 | 
					  * mgw: Allow receiving lowercase X-Osmo-Ign Callid field
 | 
				
			||||||
 | 
					  * mgw: Allow receiving uppercase noanswer keyword
 | 
				
			||||||
 | 
					  * doc: X-Osmo-IGN: small formatting and typo fixes
 | 
				
			||||||
 | 
					  * doc: Add Osmux documentation to OsmoMGW User Manual
 | 
				
			||||||
 | 
					  * Catch unsigned integer MGCP parsing errors with strtoul
 | 
				
			||||||
 | 
					  * Fix return variable of strtoul()
 | 
				
			||||||
 | 
					  * Remove undefined param passed to {logging,osmo_stats}_vty_add_cmds
 | 
				
			||||||
 | 
					  * configure.ac: Require libosmo-netif 0.6.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Alexander Couzens ]
 | 
				
			||||||
 | 
					  * mgcp_internal: LOGPENDP: ensure *endp is not NULL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Harald Welte ]
 | 
				
			||||||
 | 
					  * handle NULL return of rate_ctr_group_alloc()
 | 
				
			||||||
 | 
					  * update .gitignore
 | 
				
			||||||
 | 
					  * mgcp_sdp: Don't check if an unsigned int is below 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Vadim Yanitskiy ]
 | 
				
			||||||
 | 
					  * configure.ac: drop useless check for -fvisibility=hidden
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Daniel Willmann ]
 | 
				
			||||||
 | 
					  * manuals: Add script to regenerate vty/counter documentation
 | 
				
			||||||
 | 
					  * manuals: Update vty/counter documentation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Hoernchen ]
 | 
				
			||||||
 | 
					  * turn -Werror=null-dereference into a warning
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Pau Espin Pedrol <pespin@sysmocom.de>  Wed, 07 Aug 2019 16:52:58 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-mgw (1.5.0) unstable; urgency=medium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Pau Espin Pedrol ]
 | 
				
			||||||
 | 
					  * gitignore: Filter *.pc
 | 
				
			||||||
 | 
					  * configure: Find correct libgsm's gsm.h header
 | 
				
			||||||
 | 
					  * vty: Fix typo writing bts-jitter-buffer-delay-{min,max}
 | 
				
			||||||
 | 
					  * Remove libosmo-legacy-mgcp and osmo-bsc-mgcp
 | 
				
			||||||
 | 
					  * debian: Remove dangling symlink to osmo-bsc-mgcp.service
 | 
				
			||||||
 | 
					  * Install systemd services with autotools
 | 
				
			||||||
 | 
					  * Install sample cfg file to /etc/osmocom
 | 
				
			||||||
 | 
					  * mgcp: Fix osmux_cid_bitmap static array size calculation
 | 
				
			||||||
 | 
					  * mgcp_osmux: Use define to calculate rtp_ssrc_winlen
 | 
				
			||||||
 | 
					  * osmux: Avoid initing output without enabling osmux
 | 
				
			||||||
 | 
					  * mgcp: Log endpoint nr consistently as hex
 | 
				
			||||||
 | 
					  * osmux_send_dummy: Avoid logging incorrectly and sending if osmux not enabled
 | 
				
			||||||
 | 
					  * osmux: Don't process regular osmux frames if disabled by cfg
 | 
				
			||||||
 | 
					  * osmux: Move parse_cid of legacy dummy frames to own function
 | 
				
			||||||
 | 
					  * osmux: Make func handling dummy frames independent of endp type
 | 
				
			||||||
 | 
					  * osmux: allow enabling osmux only on correct activating state
 | 
				
			||||||
 | 
					  * osmux: Improve checks around activating and using enabled osmux
 | 
				
			||||||
 | 
					  * osmux.h: Document enum osmux_state
 | 
				
			||||||
 | 
					  * osmux: Avoid processing further frames if conn not found
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Philipp Maier ]
 | 
				
			||||||
 | 
					  * mgcp_client_fsm: allow ptmap in mgcp_client_fsm as well
 | 
				
			||||||
 | 
					  * mgcp_network: translate payload type numbers in RTP packets
 | 
				
			||||||
 | 
					  * mgcp_client: use IETF source port as for MGCP
 | 
				
			||||||
 | 
					  * mgcp_client: increment local port number when port is in use
 | 
				
			||||||
 | 
					  * mgcp_test: release endpoints after use
 | 
				
			||||||
 | 
					  * network: do not patch PT of RTCP packets
 | 
				
			||||||
 | 
					  * network: check packets before further processing
 | 
				
			||||||
 | 
					  * Cosmetic: remove misplaced line break
 | 
				
			||||||
 | 
					  * mgcp_sdp: restructure mgcp_write_response_sdp() (rtpmap)
 | 
				
			||||||
 | 
					  * mgcp_sdp: restructure mgcp_write_response_sdp() (audio)
 | 
				
			||||||
 | 
					  * mgcp_client: check local port only once
 | 
				
			||||||
 | 
					  * mgcp_client_fsm: switch to MGCP_CONN_RECV_SEND in add_audio()
 | 
				
			||||||
 | 
					  * mgcp_protocol: increase buffer space for codec name in LCO
 | 
				
			||||||
 | 
					  * osmo-mgw: Add vty reference manual
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Neels Hofmeyr ]
 | 
				
			||||||
 | 
					  * fix handling of "Wrong domain name" error
 | 
				
			||||||
 | 
					  * interpret domain '*' as 'allow any domain'
 | 
				
			||||||
 | 
					  * cosmetic: log: fix "CallIDs does not match"
 | 
				
			||||||
 | 
					  * fix 3G hack: allow any IP for loopback and 0.0.0.0
 | 
				
			||||||
 | 
					  * cosmetic: drop code dup in mgcp_client_fsm.c CRCX
 | 
				
			||||||
 | 
					  * add X-Osmo-IGN MGCP header to ignore CallID
 | 
				
			||||||
 | 
					  * X-Osmo-IGN: rather parse items by token, not char
 | 
				
			||||||
 | 
					  * mgcp_test: fix log of conn_id presence
 | 
				
			||||||
 | 
					  * mgcp_test: fix get_conn_id_from_response() CI length
 | 
				
			||||||
 | 
					  * mgcp_client_test: cosmetically re-arrange reply_to() args
 | 
				
			||||||
 | 
					  * mgcp_client_test: use "\r\n\r\n" instead of "\n\n"
 | 
				
			||||||
 | 
					  * mgcp_client_test: also verify received conn_id
 | 
				
			||||||
 | 
					  * mgcp_client_test: test long conn_id
 | 
				
			||||||
 | 
					  * mgcp_client: error on too long conn id
 | 
				
			||||||
 | 
					  * mgcp_common: rename to MGCP_CONN_ID_MAXLEN
 | 
				
			||||||
 | 
					  * doc: fix mgcp_verify_ci() return val doc
 | 
				
			||||||
 | 
					  * mgcp_verify_ci(): return meaningful error codes
 | 
				
			||||||
 | 
					  * fix mgcp_verify_ci(): off-by-one in max len check
 | 
				
			||||||
 | 
					  * generate shorter 'I:' conn IDs
 | 
				
			||||||
 | 
					  * mgcp_conn_get(): compare conn Id ('I:') case insensitively
 | 
				
			||||||
 | 
					  * mgcp_conn_get(): match conn Id ('I:') despite leading zeros
 | 
				
			||||||
 | 
					  * cosmetic: mgcp_test: fix get_conn_id_from_response()
 | 
				
			||||||
 | 
					  * comment: indicate struct type for mgcp_endpoint.conns
 | 
				
			||||||
 | 
					  * log: avoid logging early media as error
 | 
				
			||||||
 | 
					  * fix osmo-mgw -s; fixes osmo-mgw.service using -s
 | 
				
			||||||
 | 
					  * Importing history from osmo-gsm-manuals.git
 | 
				
			||||||
 | 
					  * OsmoMGW: update VTY reference
 | 
				
			||||||
 | 
					  * OsmoMGW: document the 'X-Osmo-IGN' MGCP extension
 | 
				
			||||||
 | 
					  * mgw: update vty reference
 | 
				
			||||||
 | 
					  * drop/replace very weird logging in mgcp_client.c
 | 
				
			||||||
 | 
					  * check_rtp: on IP:port errors, log the IP and port
 | 
				
			||||||
 | 
					  * osmo-mgw: err-log: include expected domain name
 | 
				
			||||||
 | 
					  * mgcp_client_vty: fix missing talloc_free
 | 
				
			||||||
 | 
					  * mgcp_client: drop a bunch of dead code
 | 
				
			||||||
 | 
					  * mgcp_client: logging tweaks
 | 
				
			||||||
 | 
					  * mgcp_client: make domain part of endpoint configurable
 | 
				
			||||||
 | 
					  * mgcp_client: tweak some log levels INFO -> {DEBUG,ERROR}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Stefan Sperling ]
 | 
				
			||||||
 | 
					  * add VTY commands which show specific mgcp endpoints
 | 
				
			||||||
 | 
					  * add MGCP CRCX command statistics to osmo-mgw
 | 
				
			||||||
 | 
					  * show RTP TX/RX stats in 'mgcp show stats' output
 | 
				
			||||||
 | 
					  * use local variable for rate counters in handle_create_con()
 | 
				
			||||||
 | 
					  * add more mgcp crxc error counters
 | 
				
			||||||
 | 
					  * add MDCX command statistics to osmo-mgw
 | 
				
			||||||
 | 
					  * add aggregated rtp connection stats to osmo-mgw
 | 
				
			||||||
 | 
					  * add DLCX command statistics to osmo-mgw
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Harald Welte ]
 | 
				
			||||||
 | 
					  * debian/rules: Don't overwrite .tarball-version
 | 
				
			||||||
 | 
					  * check_rtp_origin(): Don't memcmp sockadd_in and in_addr
 | 
				
			||||||
 | 
					  * check_rtp_origin(): Avoid using memcmp for comparing integer types
 | 
				
			||||||
 | 
					  * vty-ref: Update URI of docbook 5.0 schema
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Daniel Willmann ]
 | 
				
			||||||
 | 
					  * mgw: Add new VTY reference
 | 
				
			||||||
 | 
					  * Add initial OsmoMGW manual
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Oliver Smith ]
 | 
				
			||||||
 | 
					  * build manuals moved here from osmo-gsm-manuals.git
 | 
				
			||||||
 | 
					  * jenkins.sh: remove leftover MGCP env variable
 | 
				
			||||||
 | 
					  * Fix DISTCHECK_CONFIGURE_FLAGS override
 | 
				
			||||||
 | 
					  * contrib/jenkins.sh: build and publish manuals
 | 
				
			||||||
 | 
					  * contrib: fix makedistcheck with disabled systemd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Harald Welte <laforge@gnumonks.org>  Sun, 20 Jan 2019 15:02:18 +0100
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-mgw (1.4.0) unstable; urgency=medium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Philipp Maier ]
 | 
				
			||||||
 | 
					  * network: independently initalize state->out_stream
 | 
				
			||||||
 | 
					  * stats: use libosmocore rate counter for in/out_stream.err_ts_counter
 | 
				
			||||||
 | 
					  * mgcp_sdp: correct apidoc of mgcp_parse_sdp_data
 | 
				
			||||||
 | 
					  * vty: clean up rtp port-range command
 | 
				
			||||||
 | 
					  * sdp: remove unused alt_codec field from struct mgcp_rtp_end
 | 
				
			||||||
 | 
					  * sdp: remove circular inclusion
 | 
				
			||||||
 | 
					  * protocol: Try whole port range on port allocation
 | 
				
			||||||
 | 
					  * client: do not start connections in loopback mode
 | 
				
			||||||
 | 
					  * mgcp_network: do not log destination invalid ip/port as error
 | 
				
			||||||
 | 
					  * cosmetic: fix log output
 | 
				
			||||||
 | 
					  * conn: call talloc_free before setting the pointer to NULL
 | 
				
			||||||
 | 
					  * protocol: do not change LCO, when no LCO are present
 | 
				
			||||||
 | 
					  * protocol: reject illegal lco options
 | 
				
			||||||
 | 
					  * cosmetic: fix typo
 | 
				
			||||||
 | 
					  * mgw: clean up codec negotiation (sdp)
 | 
				
			||||||
 | 
					  * client: add features to generate and parse codec information
 | 
				
			||||||
 | 
					  * mgcp_internal: remove unused struct member
 | 
				
			||||||
 | 
					  * stats: replace packet statistic counters with libosmocore rate counters
 | 
				
			||||||
 | 
					  * stat+vty: fix printing of rate counter values
 | 
				
			||||||
 | 
					  * protocol: prevent unnecessary null pointer deref
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Pau Espin Pedrol ]
 | 
				
			||||||
 | 
					  * legacy-mgcp: Add jitter buffer on the uplink receiver
 | 
				
			||||||
 | 
					  * legacy-mgcp: switch to new osmux output APIs
 | 
				
			||||||
 | 
					  * mgcp: mgcp_osmux: use conn_bts when forwarding pkts from bsc_nat
 | 
				
			||||||
 | 
					  * mgcp: switch to new osmux output APIs
 | 
				
			||||||
 | 
					  * debian: Package installed example doc files
 | 
				
			||||||
 | 
					  * gitignore: Add m4 scripts from m4 subdir
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Neels Hofmeyr ]
 | 
				
			||||||
 | 
					  * api doc: fix parameter name for mgcp_conn_create()
 | 
				
			||||||
 | 
					  * mgcp-client: add mgcp_conn_get_ci()
 | 
				
			||||||
 | 
					  * mgcp_client_fsm: improve error logging
 | 
				
			||||||
 | 
					  * cosmetic: fix doxygen comment markers
 | 
				
			||||||
 | 
					  * cosmetic: mgcp_network.c: merge one LOGPC to its preceding LOGP
 | 
				
			||||||
 | 
					  * IuUP hack: make RTP patching less general
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Harald Welte ]
 | 
				
			||||||
 | 
					  * cosmetic: fix typo in log message: 'abrupt' instead of 'aprupt'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Daniel Willmann ]
 | 
				
			||||||
 | 
					  * git-version-gen: Don't check for .git directory
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Pau Espin Pedrol <pespin@sysmocom.de>  Fri, 27 Jul 2018 19:05:22 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-mgw (1.3.0) unstable; urgency=medium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Pau Espin Pedrol ]
 | 
				
			||||||
 | 
					  * contrib: Add osmo-mgw systemd service
 | 
				
			||||||
 | 
					  * legacy: mgcp_protocol: Don't print osmux stats if it is off
 | 
				
			||||||
 | 
					  * mgcp_stat: Don't print osmux stats if it is off
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Neels Hofmeyr ]
 | 
				
			||||||
 | 
					  * fix segfault: DLCX for unknown endpoint: dont try to log NULL endpoint
 | 
				
			||||||
 | 
					  * MGCP endpoints: parse as decimal, not hex
 | 
				
			||||||
 | 
					  * add --enable-sanitize config option
 | 
				
			||||||
 | 
					  * legacy_mgcp: mgcp_test: sanitize: free msgb_ctx
 | 
				
			||||||
 | 
					  * mgcp_test: test_packet_error_detection: sanitize: free all conns
 | 
				
			||||||
 | 
					  * mgcp_test: test_no_cycle: sanitize: free endp
 | 
				
			||||||
 | 
					  * mgcp_test: sanitize: free msgb_ctx
 | 
				
			||||||
 | 
					  * mgcp_client: don't configure "bts base"
 | 
				
			||||||
 | 
					  * Revert "mgcp_client: don't configure "bts base"" until osmo-msc is ready
 | 
				
			||||||
 | 
					  * mgcp_client: add transaction cleanup
 | 
				
			||||||
 | 
					  * mgcp_client_test makefile: add update_exp target
 | 
				
			||||||
 | 
					  * cosmetic: mgcp_network: typo in log
 | 
				
			||||||
 | 
					  * osmo-mgw: Add talloc context introspection via VTY
 | 
				
			||||||
 | 
					  * mgcp_client: show failure by MGCP SDP section parsing test
 | 
				
			||||||
 | 
					  * mgcp_client: cosmetic: clean up SDP params parsing
 | 
				
			||||||
 | 
					  * mgcp_client: detect SDP section-start parsing errors
 | 
				
			||||||
 | 
					  * compiler warning: ignore deprecated in mgcp_client_test.c
 | 
				
			||||||
 | 
					  * configure: add --enable-werror
 | 
				
			||||||
 | 
					  * jenkins.sh: add --enable-werror to configure flags
 | 
				
			||||||
 | 
					  * cosmetic: mgcp, legacy_mgcp: drop unused vty.h definitions
 | 
				
			||||||
 | 
					  * use osmo_init_logging2() with proper talloc ctx
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Philipp Maier ]
 | 
				
			||||||
 | 
					  * osmux: fix nullpointer dereference
 | 
				
			||||||
 | 
					  * cosmetic: guard dead osmux vty code with ifdef
 | 
				
			||||||
 | 
					  * cosmetic: remove prefix "net" from rtp related vty commands
 | 
				
			||||||
 | 
					  * doc: update sample config file
 | 
				
			||||||
 | 
					  * cosmetic: use correct VTY port number constant
 | 
				
			||||||
 | 
					  * vty: simplify endpoint allocation
 | 
				
			||||||
 | 
					  * vty: do not change number_endpoints at runtime
 | 
				
			||||||
 | 
					  * MGCP: Connection Identifiers are hex strings
 | 
				
			||||||
 | 
					  * libosmo-mgcp: Connection Identifiers are allocated by MGW, not CA
 | 
				
			||||||
 | 
					  * client: use osmo_strlcpy instead of strncpy
 | 
				
			||||||
 | 
					  * cosmetic: fix sourcecode formatting
 | 
				
			||||||
 | 
					  * cosmetic: clearly mark endpoint numbers as hex
 | 
				
			||||||
 | 
					  * client: use string as connection identifier
 | 
				
			||||||
 | 
					  * conn: remove assertions
 | 
				
			||||||
 | 
					  * mgcp_test: fix wrong strcmp() parameters
 | 
				
			||||||
 | 
					  * mgcp_test: fix nullpointer dereference
 | 
				
			||||||
 | 
					  * mgcp_test: add returncode check
 | 
				
			||||||
 | 
					  * mgcp_test: fix possible double free
 | 
				
			||||||
 | 
					  * mcgp_client: mgcp_msg_gen(): add checks to verify params
 | 
				
			||||||
 | 
					  * network: use originating RTP packet address for loopback
 | 
				
			||||||
 | 
					  * client: mgcp_response_parse_params: check rtp port
 | 
				
			||||||
 | 
					  * mgcp: allow endpoints beginning from zero
 | 
				
			||||||
 | 
					  * client/common: move constant MGCP_ENDPOINT_MAXLEN
 | 
				
			||||||
 | 
					  * mgcp: make domain name configurable
 | 
				
			||||||
 | 
					  * cosmetic: protocol: remove unnecessary nul termination
 | 
				
			||||||
 | 
					  * client: do not insist on \n\n when parsing MGCP messages
 | 
				
			||||||
 | 
					  * main: display mgcp ip/port
 | 
				
			||||||
 | 
					  * client: make callid in MDCX mandatory
 | 
				
			||||||
 | 
					  * client: add missing mandatory SDP fields
 | 
				
			||||||
 | 
					  * mgcp: permit wildcarded endpoint assignment (CRCX)
 | 
				
			||||||
 | 
					  * mgcp: add prefix to virtual trunk
 | 
				
			||||||
 | 
					  * client: eliminate destructive parameter parsing
 | 
				
			||||||
 | 
					  * client: eliminate destructive head parsing
 | 
				
			||||||
 | 
					  * cosmetic: client: add doxygen comments
 | 
				
			||||||
 | 
					  * protocol: fix problem with line break and OSMUX
 | 
				
			||||||
 | 
					  * protocol: fix missing carriage return
 | 
				
			||||||
 | 
					  * client: fix sdp parameter ordering
 | 
				
			||||||
 | 
					  * protocol: check the packetization in local cx options
 | 
				
			||||||
 | 
					  * cosmetic: remove spaces from pointer symbol
 | 
				
			||||||
 | 
					  * client: Do not accept endpoint ids with wildcards in responses
 | 
				
			||||||
 | 
					  * client: do not accept endpoint ids without @ character in responses
 | 
				
			||||||
 | 
					  * client: prohibit endpoint ids without @ character
 | 
				
			||||||
 | 
					  * protocol: on wildcarded CRCX return endpoint number as hex
 | 
				
			||||||
 | 
					  * msg: fix response code on exhausted endp resources
 | 
				
			||||||
 | 
					  * cosmetic: move mgcp_release_endp() to mgcp_ep.c
 | 
				
			||||||
 | 
					  * client: use heap to store mgcp_response
 | 
				
			||||||
 | 
					  * ep: move endpoint struct and define to mgcp_ep.h
 | 
				
			||||||
 | 
					  * cosmetic: rename mgcp_release_endp to mgcp_endp_release
 | 
				
			||||||
 | 
					  * cosmetic: rename mgcp_ep.c/h to mgcp_endp.c/h
 | 
				
			||||||
 | 
					  * protocol: reject DLCX/CRCX/MDCX on unsupported parameters
 | 
				
			||||||
 | 
					  * protocol: exit cleanly when local cx options check fails
 | 
				
			||||||
 | 
					  * cosmetic: Add missing \n on log line
 | 
				
			||||||
 | 
					  * protocol: check requested connection mode
 | 
				
			||||||
 | 
					  * protocol: fix tagging of wildcarded requests
 | 
				
			||||||
 | 
					  * protocol: prohibit wildcarded requests for MDCX and DLCX
 | 
				
			||||||
 | 
					  * mgcp: fix use-after-free and add callback for endpoint cleanup
 | 
				
			||||||
 | 
					  * client: add an optional FSM interface
 | 
				
			||||||
 | 
					  * mgcp_client_fsm: Add FSM event names
 | 
				
			||||||
 | 
					  * cosmetic: mgcp_client_fsm: rename enums
 | 
				
			||||||
 | 
					  * cosmetic: rename function .._conn_reset() to .._conn_init()
 | 
				
			||||||
 | 
					  * mgcp_conn: do not touch u.rtp in mgcp_conn_alloc()
 | 
				
			||||||
 | 
					  * cosmetic: rename .._codec_reset() to .._codec_init()
 | 
				
			||||||
 | 
					  * mgcp_conn: add function mgcp_rtp_conn_cleanup()
 | 
				
			||||||
 | 
					  * stats: use libosmocore rate counter for in/out_stream.err_ts_counter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Alexander Couzens ]
 | 
				
			||||||
 | 
					  * debian/control: correct library dependency of osmo-mgw against libosmo-mgcp1
 | 
				
			||||||
 | 
					  * debian: include systemd service osmo-mgw.service
 | 
				
			||||||
 | 
					  * Revert "stats: use libosmocore rate counter for in/out_stream.err_ts_counter"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Harald Welte ]
 | 
				
			||||||
 | 
					  * cosmetic: fix whitespaces; we use tabs for indentation
 | 
				
			||||||
 | 
					  * Fix possible buffer overflow in mgcp_conn_dump()
 | 
				
			||||||
 | 
					  * osmo-mgw: Update copyright statement
 | 
				
			||||||
 | 
					  * osmo-mgw: Config file is osmo-mgw.cfg, and not mgcp.cfg
 | 
				
			||||||
 | 
					  * osmo-mgw: Fix copyright notice
 | 
				
			||||||
 | 
					  * strct mgcp_rtp_state: Group + document struct members related to patching
 | 
				
			||||||
 | 
					  * mgcp_rtp_state: grup 'stats' members into sub-structure
 | 
				
			||||||
 | 
					  * mgcp_rtp_end: Group statistics members into 'stats' sub-struct
 | 
				
			||||||
 | 
					  * libosmo-mgcp: Cosmetic spelling fixes in comments
 | 
				
			||||||
 | 
					  * mgcp_msg: We must parse endpoint numbers as hex, not decimal!
 | 
				
			||||||
 | 
					  * mgcp_internal.h: document more struct members with comments
 | 
				
			||||||
 | 
					  * centralize handling of common errors like "endpoint not found"
 | 
				
			||||||
 | 
					  * Return proper MGCP Error codes, as per spec
 | 
				
			||||||
 | 
					  * osmo-mgw: Use libosmocore socket abstraction
 | 
				
			||||||
 | 
					  * osmo-bsc_mgcp: Add LIBOSMONETIF_{CFLAGS,LIBS}
 | 
				
			||||||
 | 
					  * libosmo-mgcp-client is GPLv2+, not AGPLv3+
 | 
				
			||||||
 | 
					  * Turn libosmo-mgcp into local, non-installed library
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Stefan Sperling ]
 | 
				
			||||||
 | 
					  * enable osmo_fsm vty commands in libosmo-mgcp-client vty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Pau Espin Pedrol <pespin@sysmocom.de>  Thu, 03 May 2018 17:40:35 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
osmo-mgw (1.2.0) unstable; urgency=medium
 | 
					osmo-mgw (1.2.0) unstable; urgency=medium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  [ Neels Hofmeyr ]
 | 
					  [ Neels Hofmeyr ]
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										57
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										57
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							@@ -1,13 +1,15 @@
 | 
				
			|||||||
Source: osmo-mgw
 | 
					Source: osmo-mgw
 | 
				
			||||||
Section: net
 | 
					Section: net
 | 
				
			||||||
Priority: extra
 | 
					Priority: extra
 | 
				
			||||||
Maintainer: Alexander Couzens <lynxis@fe80.eu>
 | 
					Maintainer: Osmocom team <openbsc@lists.osmocom.org>
 | 
				
			||||||
Build-Depends: debhelper (>=9),
 | 
					Build-Depends: debhelper (>=9),
 | 
				
			||||||
               dh-autoreconf,
 | 
					               dh-autoreconf,
 | 
				
			||||||
               pkg-config,
 | 
					               pkg-config,
 | 
				
			||||||
               autotools-dev,
 | 
					               autotools-dev,
 | 
				
			||||||
               libosmocore-dev,
 | 
					               libosmocore-dev (>= 1.6.0),
 | 
				
			||||||
               libosmo-netif-dev
 | 
					               libosmo-netif-dev (>= 1.1.0),
 | 
				
			||||||
 | 
					               libosmo-abis-dev (>= 1.2.0),
 | 
				
			||||||
 | 
					               osmo-gsm-manuals-dev (>= 1.2.0)
 | 
				
			||||||
Standards-Version: 3.9.8
 | 
					Standards-Version: 3.9.8
 | 
				
			||||||
Vcs-Git: git://git.osmocom.org/osmo-mgw.git
 | 
					Vcs-Git: git://git.osmocom.org/osmo-mgw.git
 | 
				
			||||||
Vcs-Browser: https://git.osmocom.org/osmo-mgw/
 | 
					Vcs-Browser: https://git.osmocom.org/osmo-mgw/
 | 
				
			||||||
@@ -16,25 +18,10 @@ Homepage: https://osmocom.org/projects/osmo-mgw
 | 
				
			|||||||
Package: osmo-mgw
 | 
					Package: osmo-mgw
 | 
				
			||||||
Architecture: any
 | 
					Architecture: any
 | 
				
			||||||
Multi-Arch: foreign
 | 
					Multi-Arch: foreign
 | 
				
			||||||
Depends: libosmo-mgcp0, ${misc:Depends}, ${shlibs:Depends}
 | 
					Depends: ${misc:Depends}, ${shlibs:Depends}
 | 
				
			||||||
Description: OsmoMGW: Osmocom's Media Gateway for 2G and 3G circuit-switched mobile networks
 | 
					Description: OsmoMGW: Osmocom's Media Gateway for 2G and 3G circuit-switched mobile networks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Package: libosmo-mgcp1
 | 
					Package: libosmo-mgcp-client9
 | 
				
			||||||
Section: libs
 | 
					 | 
				
			||||||
Architecture: any
 | 
					 | 
				
			||||||
Multi-Arch: same
 | 
					 | 
				
			||||||
Pre-Depends: ${misc:Pre-Depends}
 | 
					 | 
				
			||||||
Depends: ${misc:Depends}, ${shlibs:Depends}
 | 
					 | 
				
			||||||
Description: libosmo-mgcp: Osmocom's Media Gateway server library
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Package: libosmo-mgcp-dev
 | 
					 | 
				
			||||||
Section: libdevel
 | 
					 | 
				
			||||||
Architecture: any
 | 
					 | 
				
			||||||
Multi-Arch: same
 | 
					 | 
				
			||||||
Depends: libosmo-mgcp1 (= ${binary:Version}), ${misc:Depends}
 | 
					 | 
				
			||||||
Description: libosmo-mgcp: Osmocom's Media Gateway server library
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Package: libosmo-mgcp-client2
 | 
					 | 
				
			||||||
Section: libs
 | 
					Section: libs
 | 
				
			||||||
Architecture: any
 | 
					Architecture: any
 | 
				
			||||||
Multi-Arch: same
 | 
					Multi-Arch: same
 | 
				
			||||||
@@ -46,26 +33,14 @@ Package: libosmo-mgcp-client-dev
 | 
				
			|||||||
Section: libdevel
 | 
					Section: libdevel
 | 
				
			||||||
Architecture: any
 | 
					Architecture: any
 | 
				
			||||||
Multi-Arch: same
 | 
					Multi-Arch: same
 | 
				
			||||||
Depends: libosmo-mgcp-client2 (= ${binary:Version}), ${misc:Depends}
 | 
					Depends: libosmo-mgcp-client9 (= ${binary:Version}), ${misc:Depends}
 | 
				
			||||||
Description: libosmo-mgcp-client: Osmocom's Media Gateway Control Protocol client utilities
 | 
					Description: libosmo-mgcp-client: Osmocom's Media Gateway Control Protocol client utilities
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Package: osmo-bsc-mgcp
 | 
					Package: osmo-mgw-doc
 | 
				
			||||||
Architecture: any
 | 
					Architecture: all
 | 
				
			||||||
Multi-Arch: foreign
 | 
					Section: doc
 | 
				
			||||||
Depends: libosmo-legacy-mgcp0, ${misc:Depends}, ${shlibs:Depends}
 | 
					Priority: optional
 | 
				
			||||||
Description: OsmoBSC-MGCP: Osmocom's Legacy Media Gateway; use osmo-mgw instead.
 | 
					Depends: ${misc:Depends}
 | 
				
			||||||
 | 
					Description: ${misc:Package} PDF documentation
 | 
				
			||||||
Package: libosmo-legacy-mgcp0
 | 
					 Various manuals: user manual, VTY reference manual and/or
 | 
				
			||||||
Section: libs
 | 
					 protocol/interface manuals.
 | 
				
			||||||
Architecture: any
 | 
					 | 
				
			||||||
Multi-Arch: same
 | 
					 | 
				
			||||||
Pre-Depends: ${misc:Pre-Depends}
 | 
					 | 
				
			||||||
Depends: ${misc:Depends}, ${shlibs:Depends}
 | 
					 | 
				
			||||||
Description: libosmo-legacy-mgcp: Osmocom's Legacy Media Gateway server library; use libosmo-mgcp instead.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Package: libosmo-legacy-mgcp-dev
 | 
					 | 
				
			||||||
Section: libdevel
 | 
					 | 
				
			||||||
Architecture: any
 | 
					 | 
				
			||||||
Multi-Arch: same
 | 
					 | 
				
			||||||
Depends: libosmo-legacy-mgcp0 (= ${binary:Version}), ${misc:Depends}
 | 
					 | 
				
			||||||
Description: libosmo-legacy-mgcp: Osmocom's Legacy Media Gateway server library; use libosmo-mgcp instead.
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										29
									
								
								debian/copyright
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										29
									
								
								debian/copyright
									
									
									
									
										vendored
									
									
								
							@@ -21,11 +21,12 @@ License:   AGPL-3.0+
 | 
				
			|||||||
 You should have received a copy of the GNU Affero General Public License
 | 
					 You should have received a copy of the GNU Affero General Public License
 | 
				
			||||||
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Files:     src/libosmo-legacy-mgcp/g711common.h
 | 
					Files:     src/libosmo-mgcp-client/* include/osmocom/mgcp_client/*
 | 
				
			||||||
Copyright: 2000 Abramo Bagnara <abramo@alsa-project.org>
 | 
					Copyright: 2016 by sysmocom s.m.f.c. GmbH <info@sysmocom.de>
 | 
				
			||||||
 | 
					           Based on OpenBSC interface to quagga VTY (libmsc/vty_interface_layer3.c)
 | 
				
			||||||
 | 
					           2009 by Harald Welte <laforge@gnumonks.org>
 | 
				
			||||||
 | 
					           2009-2011 by Holger Hans Peter Freyther
 | 
				
			||||||
License:   GPL-2.0+
 | 
					License:   GPL-2.0+
 | 
				
			||||||
 Wrapper for linphone Codec class by Simon Morlat <simon.morlat@linphone.org>
 | 
					 | 
				
			||||||
 .
 | 
					 | 
				
			||||||
 This program is free software; you can redistribute it and/or modify
 | 
					 This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 it under the terms of the GNU General Public License as published by
 | 
					 it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 the Free Software Foundation; either version 2 of the License, or
 | 
					 the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
@@ -37,13 +38,7 @@ License:   GPL-2.0+
 | 
				
			|||||||
 GNU General Public License for more details.
 | 
					 GNU General Public License for more details.
 | 
				
			||||||
 .
 | 
					 .
 | 
				
			||||||
 You should have received a copy of the GNU General Public License
 | 
					 You should have received a copy of the GNU General Public License
 | 
				
			||||||
 along with this program; if not, write to the Free Software
 | 
					 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
					 | 
				
			||||||
 .
 | 
					 | 
				
			||||||
 The FSF address in the above text is the old one.
 | 
					 | 
				
			||||||
 .
 | 
					 | 
				
			||||||
 On Debian systems, the complete text of the GNU General Public License
 | 
					 | 
				
			||||||
 Version 2 can be found in `/usr/share/common-licenses/GPL-2'.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
Files:     tests/vty_test_runner.py
 | 
					Files:     tests/vty_test_runner.py
 | 
				
			||||||
Copyright: 2013 Holger Hans Peter Freyther
 | 
					Copyright: 2013 Holger Hans Peter Freyther
 | 
				
			||||||
@@ -68,15 +63,3 @@ License:   GPL-3.0+
 | 
				
			|||||||
Files:     osmoappdesc.py
 | 
					Files:     osmoappdesc.py
 | 
				
			||||||
Copyright: 2013 Katerina Barone-Adesi <kat.obsc@gmail.com>
 | 
					Copyright: 2013 Katerina Barone-Adesi <kat.obsc@gmail.com>
 | 
				
			||||||
License:   GPL-3.0+
 | 
					License:   GPL-3.0+
 | 
				
			||||||
 | 
					 | 
				
			||||||
Files:     src/libosmo-legacy-mgcp/mgcp_osmux.c
 | 
					 | 
				
			||||||
Copyright: 2012-2013 On Waves ehf <http://www.on-waves.com>
 | 
					 | 
				
			||||||
           2012-2013 Pablo Neira Ayuso <pablo@gnumonks.org>
 | 
					 | 
				
			||||||
License:   AGPL-3.0+
 | 
					 | 
				
			||||||
 All rights not specifically granted under this license are reserved.
 | 
					 | 
				
			||||||
 .
 | 
					 | 
				
			||||||
 This program is free software; you can redistribute it and/or modify it
 | 
					 | 
				
			||||||
 under the terms of the GNU Affero General Public License as published by the
 | 
					 | 
				
			||||||
 Free Software Foundation; either version 3 of the License, or (at your
 | 
					 | 
				
			||||||
 option) any later version.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										4
									
								
								debian/libosmo-legacy-mgcp-dev.install
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								debian/libosmo-legacy-mgcp-dev.install
									
									
									
									
										vendored
									
									
								
							@@ -1,4 +0,0 @@
 | 
				
			|||||||
usr/include/osmocom/legacy_mgcp
 | 
					 | 
				
			||||||
usr/lib/*/libosmo-legacy-mgcp.so
 | 
					 | 
				
			||||||
usr/lib/*/libosmo-legacy-mgcp.a
 | 
					 | 
				
			||||||
usr/lib/*/pkgconfig/libosmo-legacy-mgcp.pc
 | 
					 | 
				
			||||||
							
								
								
									
										1
									
								
								debian/libosmo-legacy-mgcp0.install
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								debian/libosmo-legacy-mgcp0.install
									
									
									
									
										vendored
									
									
								
							@@ -1 +0,0 @@
 | 
				
			|||||||
usr/lib/*/libosmo-legacy-mgcp.so.*
 | 
					 | 
				
			||||||
							
								
								
									
										4
									
								
								debian/libosmo-mgcp-dev.install
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								debian/libosmo-mgcp-dev.install
									
									
									
									
										vendored
									
									
								
							@@ -1,4 +0,0 @@
 | 
				
			|||||||
usr/include/osmocom/mgcp
 | 
					 | 
				
			||||||
usr/lib/*/libosmo-mgcp.so
 | 
					 | 
				
			||||||
usr/lib/*/libosmo-mgcp.a
 | 
					 | 
				
			||||||
usr/lib/*/pkgconfig/libosmo-mgcp.pc
 | 
					 | 
				
			||||||
							
								
								
									
										1
									
								
								debian/libosmo-mgcp1.install
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								debian/libosmo-mgcp1.install
									
									
									
									
										vendored
									
									
								
							@@ -1 +0,0 @@
 | 
				
			|||||||
usr/lib/*/libosmo-mgcp.so.*
 | 
					 | 
				
			||||||
							
								
								
									
										1
									
								
								debian/osmo-bsc-mgcp.install
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								debian/osmo-bsc-mgcp.install
									
									
									
									
										vendored
									
									
								
							@@ -1 +0,0 @@
 | 
				
			|||||||
usr/bin/osmo-bsc_mgcp
 | 
					 | 
				
			||||||
							
								
								
									
										1
									
								
								debian/osmo-bsc-mgcp.service
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								debian/osmo-bsc-mgcp.service
									
									
									
									
										vendored
									
									
								
							@@ -1 +0,0 @@
 | 
				
			|||||||
../contrib/systemd/osmo-bsc-mgcp.service
 | 
					 | 
				
			||||||
							
								
								
									
										1
									
								
								debian/osmo-mgw-doc.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								debian/osmo-mgw-doc.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					usr/share/doc/osmo-mgw-doc/*.pdf
 | 
				
			||||||
							
								
								
									
										4
									
								
								debian/osmo-mgw.install
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								debian/osmo-mgw.install
									
									
									
									
										vendored
									
									
								
							@@ -1 +1,5 @@
 | 
				
			|||||||
 | 
					etc/osmocom/osmo-mgw.cfg
 | 
				
			||||||
 | 
					lib/systemd/system/osmo-mgw.service
 | 
				
			||||||
usr/bin/osmo-mgw
 | 
					usr/bin/osmo-mgw
 | 
				
			||||||
 | 
					usr/share/doc/osmo-mgw/examples/osmo-mgw/osmo-mgw.cfg
 | 
				
			||||||
 | 
					usr/share/doc/osmo-mgw/examples/osmo-mgw/osmo-mgw-abis_e1.cfg
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										9
									
								
								debian/rules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								debian/rules
									
									
									
									
										vendored
									
									
								
							@@ -29,8 +29,11 @@ CFLAGS += -g
 | 
				
			|||||||
override_dh_auto_test:
 | 
					override_dh_auto_test:
 | 
				
			||||||
	dh_auto_test || (find . -name testsuite.log -exec cat {} \; ; false)
 | 
						dh_auto_test || (find . -name testsuite.log -exec cat {} \; ; false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
override_dh_autoreconf:
 | 
					override_dh_auto_configure:
 | 
				
			||||||
	echo $(VERSION) > .tarball-version
 | 
						dh_auto_configure -- --with-systemdsystemunitdir=/lib/systemd/system --enable-manuals
 | 
				
			||||||
	dh_autoreconf
 | 
					
 | 
				
			||||||
 | 
					# Don't create .pdf.gz files (barely saves space and they can't be opened directly by most pdf readers)
 | 
				
			||||||
 | 
					override_dh_compress:
 | 
				
			||||||
 | 
						dh_compress -X.pdf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# See https://www.debian.org/doc/manuals/developers-reference/best-pkging-practices.html#bpp-dbg
 | 
					# See https://www.debian.org/doc/manuals/developers-reference/best-pkging-practices.html#bpp-dbg
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,4 @@
 | 
				
			|||||||
SUBDIRS = \
 | 
					SUBDIRS = \
 | 
				
			||||||
	examples \
 | 
						examples \
 | 
				
			||||||
 | 
						manuals \
 | 
				
			||||||
	$(NULL)
 | 
						$(NULL)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,11 @@
 | 
				
			|||||||
 | 
					OSMOCONF_FILES = \
 | 
				
			||||||
 | 
						osmo-mgw/osmo-mgw.cfg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmoconfdir = $(sysconfdir)/osmocom
 | 
				
			||||||
 | 
					osmoconf_DATA = $(OSMOCONF_FILES)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EXTRA_DIST = $(OSMOCONF_FILES)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CFG_FILES = find $(srcdir) -name '*.cfg*' | sed -e 's,^$(srcdir),,'
 | 
					CFG_FILES = find $(srcdir) -name '*.cfg*' | sed -e 's,^$(srcdir),,'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dist-hook:
 | 
					dist-hook:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,14 +0,0 @@
 | 
				
			|||||||
!
 | 
					 | 
				
			||||||
! MGCP configuration example
 | 
					 | 
				
			||||||
!
 | 
					 | 
				
			||||||
mgcp
 | 
					 | 
				
			||||||
 !local ip 10.23.24.2
 | 
					 | 
				
			||||||
 !bts ip 10.24.24.1
 | 
					 | 
				
			||||||
 !bind ip 10.23.24.1
 | 
					 | 
				
			||||||
 bind port 2427
 | 
					 | 
				
			||||||
 rtp base 4000
 | 
					 | 
				
			||||||
 rtp force-ptime 20
 | 
					 | 
				
			||||||
 sdp audio payload number 98
 | 
					 | 
				
			||||||
 sdp audio payload name AMR/8000
 | 
					 | 
				
			||||||
 number endpoints 31
 | 
					 | 
				
			||||||
 no rtcp-omit
 | 
					 | 
				
			||||||
							
								
								
									
										25
									
								
								doc/examples/osmo-mgw/osmo-mgw-abis_e1.cfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								doc/examples/osmo-mgw/osmo-mgw-abis_e1.cfg
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					!
 | 
				
			||||||
 | 
					! MGCP configuration example
 | 
				
			||||||
 | 
					!
 | 
				
			||||||
 | 
					e1_input
 | 
				
			||||||
 | 
					 e1_line 0 driver dahdi
 | 
				
			||||||
 | 
					 e1_line 0 port 0
 | 
				
			||||||
 | 
					mgcp
 | 
				
			||||||
 | 
					  bind ip 127.0.0.1
 | 
				
			||||||
 | 
					  rtp port-range 4002 16000
 | 
				
			||||||
 | 
					  rtp bind-ip 127.0.0.1
 | 
				
			||||||
 | 
					  rtp ip-probing
 | 
				
			||||||
 | 
					  rtp ip-dscp 46
 | 
				
			||||||
 | 
					  bind port 2427
 | 
				
			||||||
 | 
					  sdp audio payload number 98
 | 
				
			||||||
 | 
					  sdp audio payload name GSM
 | 
				
			||||||
 | 
					  number endpoints 512
 | 
				
			||||||
 | 
					  loop 0
 | 
				
			||||||
 | 
					  force-realloc 1
 | 
				
			||||||
 | 
					  rtcp-omit
 | 
				
			||||||
 | 
					  rtp-patch ssrc
 | 
				
			||||||
 | 
					  rtp-patch timestamp
 | 
				
			||||||
 | 
					  trunk 1
 | 
				
			||||||
 | 
					   rtp keep-alive once
 | 
				
			||||||
 | 
					   no rtp keep-alive
 | 
				
			||||||
 | 
					   line 0
 | 
				
			||||||
@@ -2,12 +2,17 @@
 | 
				
			|||||||
! MGCP configuration example
 | 
					! MGCP configuration example
 | 
				
			||||||
!
 | 
					!
 | 
				
			||||||
mgcp
 | 
					mgcp
 | 
				
			||||||
 !local ip 10.23.24.2
 | 
					  bind ip 127.0.0.1
 | 
				
			||||||
 !bts ip 10.24.24.1
 | 
					  rtp port-range 4002 16000
 | 
				
			||||||
 !bind ip 10.23.24.1
 | 
					  rtp bind-ip 127.0.0.1
 | 
				
			||||||
 | 
					  rtp ip-probing
 | 
				
			||||||
 | 
					  rtp ip-dscp 46
 | 
				
			||||||
  bind port 2427
 | 
					  bind port 2427
 | 
				
			||||||
 rtp force-ptime 20
 | 
					 | 
				
			||||||
  sdp audio payload number 98
 | 
					  sdp audio payload number 98
 | 
				
			||||||
 sdp audio payload name AMR/8000
 | 
					  sdp audio payload name GSM
 | 
				
			||||||
 number endpoints 31
 | 
					  number endpoints 512
 | 
				
			||||||
 no rtcp-omit
 | 
					  loop 0
 | 
				
			||||||
 | 
					  force-realloc 1
 | 
				
			||||||
 | 
					  rtcp-omit
 | 
				
			||||||
 | 
					  rtp-patch ssrc
 | 
				
			||||||
 | 
					  rtp-patch timestamp
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										23
									
								
								doc/manuals/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								doc/manuals/Makefile.am
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					EXTRA_DIST = osmomgw-usermanual.adoc \
 | 
				
			||||||
 | 
					    osmomgw-usermanual-docinfo.xml \
 | 
				
			||||||
 | 
					    osmomgw-vty-reference.xml \
 | 
				
			||||||
 | 
					    regen_doc.sh \
 | 
				
			||||||
 | 
					    chapters \
 | 
				
			||||||
 | 
					    vty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if BUILD_MANUALS
 | 
				
			||||||
 | 
					  ASCIIDOC = osmomgw-usermanual.adoc
 | 
				
			||||||
 | 
					  ASCIIDOC_DEPS = $(srcdir)/chapters/*.adoc
 | 
				
			||||||
 | 
					  include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.asciidoc.inc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  VTY_REFERENCE = osmomgw-vty-reference.xml
 | 
				
			||||||
 | 
					  include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.vty-reference.inc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  BUILT_REFERENCE_XML = $(builddir)/vty/mgw_vty_reference.xml
 | 
				
			||||||
 | 
					  $(builddir)/vty/mgw_vty_reference.xml: $(top_builddir)/src/osmo-mgw/osmo-mgw
 | 
				
			||||||
 | 
						mkdir -p $(builddir)/vty
 | 
				
			||||||
 | 
						$(top_builddir)/src/osmo-mgw/osmo-mgw --vty-ref-xml > $@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  OSMO_REPOSITORY = osmo-mgw
 | 
				
			||||||
 | 
					  include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.common.inc
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
							
								
								
									
										124
									
								
								doc/manuals/chapters/configuration.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								doc/manuals/chapters/configuration.adoc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,124 @@
 | 
				
			|||||||
 | 
					== Configuring OsmoMGW
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A basic configation of OsmoMGW mainly consists of specifying the IP address
 | 
				
			||||||
 | 
					and port on which to listen to MGCP commands, but changing the port range at
 | 
				
			||||||
 | 
					which the RTP streams terminate as well as limiting operation to a single call
 | 
				
			||||||
 | 
					agent can be done as well as changing the number of endpoints.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== Configuring MGCP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					By default OsmoMGW listens for MGCP on port 2427 on any IP address. If a call
 | 
				
			||||||
 | 
					agent address is configured then OsmoMGW will only answer MGCP commands from
 | 
				
			||||||
 | 
					that IP port 2727, otherwise all sources are handled. A domain can be
 | 
				
			||||||
 | 
					specified
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.Example: MGCP configuration
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					OsmoMGW(config-mgcp)# bind ip 127.0.0.1
 | 
				
			||||||
 | 
					OsmoMGW(config-mgcp)# bind port 2427
 | 
				
			||||||
 | 
					OsmoMGW(config-mgcp)# call-agent ip 127.0.0.1
 | 
				
			||||||
 | 
					OsmoMGW(config-mgcp)# domain mgw-bsc
 | 
				
			||||||
 | 
					OsmoMGW(config-mgcp)# local ip 127.0.0.1
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== Configuring the trunk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The first trunk is considered a virtual trunk in OsmoMGW. All
 | 
				
			||||||
 | 
					endpoints of type "rtpbridge" are routed here. The virtual trunk is configured
 | 
				
			||||||
 | 
					in the config-mgcp context.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					All other trunks are configured in the config-mgcp-trunk context, but the
 | 
				
			||||||
 | 
					commands used are identical. Right now trunks are considered only for "ds/e1"
 | 
				
			||||||
 | 
					type endpoints.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.Example: MGCP trunk configuration
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					OsmoMGW(config-mgcp)# number endpoints 63 <1>
 | 
				
			||||||
 | 
					OsmoMGW(config-mgcp)# rtp bind-ip 10.0.0.1 <2>
 | 
				
			||||||
 | 
					OsmoMGW(config-mgcp)# rtp port-range 12000-14000 <3>
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					<1> Maximum number of endpoints that can be allocated at once
 | 
				
			||||||
 | 
					<2> Use this IP when binding RTP endpoints
 | 
				
			||||||
 | 
					<3> Use ports in this range when binding RTP endpoints
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					There are some options to tweak how RTP forwarding behaves in OsmoMGW:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.Example: MGCP trunk rtp options
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					OsmoMGW(config-mgcp)# rtp keep-alive 30 <1>
 | 
				
			||||||
 | 
					OsmoMGW(config-mgcp)# rtp-patch ssrc <2>
 | 
				
			||||||
 | 
					OsmoMGW(config-mgcp)# rtp-patch timestamp <3>
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					<1> Send dummy UDP packets periodically to RTP destination
 | 
				
			||||||
 | 
					<2> Hide SSRC changes
 | 
				
			||||||
 | 
					<3> Ensure RTP timestamp is aligned with frame duration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NOTE: Changes to trunks that affect resource allocation, such as newly created
 | 
				
			||||||
 | 
					trunks or a change of the number of available endpoints, require a full restart
 | 
				
			||||||
 | 
					of osmo-mgw!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== E1 trunk considerations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					While the RTP bridge trunks are natively based on IP no special considerations
 | 
				
			||||||
 | 
					are required during setup. E1 trunks are mapped on a physical E1 line, which has
 | 
				
			||||||
 | 
					to be configured as shown below.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.Example: E1 line setup
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					OsmoMGW(config-e1_input)# e1_line 0 driver dahdi <1>
 | 
				
			||||||
 | 
					OsmoMGW(config-e1_input)# e1_line 0 port 2 <2>
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					<1> Name of the libosmo-abis driver implementation ("dahdi")
 | 
				
			||||||
 | 
					<2> Port number of the physical E1 port to use (2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In osmo-mgw the e1_input node is used to configure the physical E1 line. The
 | 
				
			||||||
 | 
					line number will be used internally to identify the configured E1 line. The
 | 
				
			||||||
 | 
					port number is the physical E1 connector (sometimes called 'span') at the E1
 | 
				
			||||||
 | 
					hardware. Per trunk an individual E1 line will be needed. Beware that the E1
 | 
				
			||||||
 | 
					driver may also need configuration settings that are not discussed here.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.Example: E1 trunk setup
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					OsmoMGW(config-mgcp)# trunk 0 <1>
 | 
				
			||||||
 | 
					OsmoMGW(config-mgcp-trunk)# line 0 <2>
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					<1> Creation of a trunk (0)
 | 
				
			||||||
 | 
					<2> Reference to the E1 line to use (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The E1 trunk is created along with a number, typically starting at 0, but if
 | 
				
			||||||
 | 
					required any number from 0-64 is allowed. The E1 trunk configuration concerning
 | 
				
			||||||
 | 
					the IP related aspects is nearly identical to the configuration of the virtual
 | 
				
			||||||
 | 
					trunk. However, it is important that the user assigns one of the E1 line numbers
 | 
				
			||||||
 | 
					that were configured under the e1_input node.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.Example: A typical configuration with one E1 trunk
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					e1_input
 | 
				
			||||||
 | 
					 e1_line 0 driver dahdi
 | 
				
			||||||
 | 
					 e1_line 0 port 2
 | 
				
			||||||
 | 
					mgcp
 | 
				
			||||||
 | 
					 bind ip 127.0.0.1
 | 
				
			||||||
 | 
					 rtp net-range 6000 6011
 | 
				
			||||||
 | 
					 rtp net-bind-ip 192.168.100.130
 | 
				
			||||||
 | 
					 rtp ip-probing
 | 
				
			||||||
 | 
					 rtp ip-dscp 46
 | 
				
			||||||
 | 
					 no rtp keep-alive
 | 
				
			||||||
 | 
					 bind port 2428
 | 
				
			||||||
 | 
					 number endpoints 30
 | 
				
			||||||
 | 
					 loop 0
 | 
				
			||||||
 | 
					 force-realloc 1
 | 
				
			||||||
 | 
					 osmux off
 | 
				
			||||||
 | 
					 rtp-patch rfc5993hr
 | 
				
			||||||
 | 
					 trunk 0
 | 
				
			||||||
 | 
					  rtp keep-alive once
 | 
				
			||||||
 | 
					  no rtp keep-alive
 | 
				
			||||||
 | 
					  line 0
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NOTE: One E1 trunk always covers a whole E1 line. All subslots (I.640) will be mapped
 | 
				
			||||||
 | 
					to individual MGCP endpoints. As long as the endpoints remain unused the
 | 
				
			||||||
 | 
					underlying E1 timeslot is not used.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NOTE: The E1 trunk implementation also works with T1 lines, however since T1 has
 | 
				
			||||||
 | 
					24 instead of 31 usable timeslots only the endpoints that fall into that 1-24 timeslot
 | 
				
			||||||
 | 
					range will be useable.
 | 
				
			||||||
							
								
								
									
										4
									
								
								doc/manuals/chapters/counters.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								doc/manuals/chapters/counters.adoc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					[[counters]]
 | 
				
			||||||
 | 
					== Counters
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::./counters_generated.adoc[]
 | 
				
			||||||
							
								
								
									
										83
									
								
								doc/manuals/chapters/counters_generated.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								doc/manuals/chapters/counters_generated.adoc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,83 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					// autogenerated by show asciidoc counters
 | 
				
			||||||
 | 
					These counters and their description based on OsmoMGW 1.5.0.64-189f (OsmoMGW).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== Rate Counters
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// generating tables for rate_ctr_group
 | 
				
			||||||
 | 
					// rate_ctr_group table aggregated statistics for all rtp connections
 | 
				
			||||||
 | 
					.all_rtp_conn - aggregated statistics for all rtp connections
 | 
				
			||||||
 | 
					[options="header"]
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					| Name | Reference | Description
 | 
				
			||||||
 | 
					| all_rtp:err_tstmp_in | <<all_rtp_conn_all_rtp:err_tstmp_in>> | Total inbound rtp-stream timestamp errors.
 | 
				
			||||||
 | 
					| all_rtp:err_tstmp_out | <<all_rtp_conn_all_rtp:err_tstmp_out>> | Total outbound rtp-stream timestamp errors.
 | 
				
			||||||
 | 
					| all_rtp:packets_rx | <<all_rtp_conn_all_rtp:packets_rx>> | Total inbound rtp packets.
 | 
				
			||||||
 | 
					| all_rtp:octets_rx | <<all_rtp_conn_all_rtp:octets_rx>> | Total inbound rtp octets.
 | 
				
			||||||
 | 
					| all_rtp:packets_tx | <<all_rtp_conn_all_rtp:packets_tx>> | Total outbound rtp packets.
 | 
				
			||||||
 | 
					| all_rtp:octets_tx | <<all_rtp_conn_all_rtp:octets_tx>> | Total outbound rtp octets.
 | 
				
			||||||
 | 
					| all_rtp:dropped | <<all_rtp_conn_all_rtp:dropped>> | Total dropped rtp packets.
 | 
				
			||||||
 | 
					| all_rtp:num_closed_conns | <<all_rtp_conn_all_rtp:num_closed_conns>> | Total number of rtp connections closed.
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					// rate_ctr_group table dlcx statistics
 | 
				
			||||||
 | 
					.dlcx - dlcx statistics
 | 
				
			||||||
 | 
					[options="header"]
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					| Name | Reference | Description
 | 
				
			||||||
 | 
					| dlcx:success | <<dlcx_dlcx:success>> | DLCX command processed successfully.
 | 
				
			||||||
 | 
					| dlcx:wildcard | <<dlcx_dlcx:wildcard>> | wildcard names in DLCX commands are unsupported.
 | 
				
			||||||
 | 
					| dlcx:no_conn | <<dlcx_dlcx:no_conn>> | endpoint specified in DLCX command has no active connections.
 | 
				
			||||||
 | 
					| dlcx:callid | <<dlcx_dlcx:callid>> | CallId specified in DLCX command mismatches endpoint's CallId .
 | 
				
			||||||
 | 
					| dlcx:connid | <<dlcx_dlcx:connid>> | connection ID specified in DLCX command does not exist on endpoint.
 | 
				
			||||||
 | 
					| dlcx:unhandled_param | <<dlcx_dlcx:unhandled_param>> | unhandled parameter in DLCX command.
 | 
				
			||||||
 | 
					| dlcx:rejected | <<dlcx_dlcx:rejected>> | connection deletion rejected by policy.
 | 
				
			||||||
 | 
					| dlcx:deferred | <<dlcx_dlcx:deferred>> | connection deletion deferred by policy.
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					// rate_ctr_group table mdcx statistics
 | 
				
			||||||
 | 
					.mdcx - mdcx statistics
 | 
				
			||||||
 | 
					[options="header"]
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					| Name | Reference | Description
 | 
				
			||||||
 | 
					| mdcx:success | <<mdcx_mdcx:success>> | MDCX command processed successfully.
 | 
				
			||||||
 | 
					| mdcx:wildcard | <<mdcx_mdcx:wildcard>> | wildcard endpoint names in MDCX commands are unsupported.
 | 
				
			||||||
 | 
					| mdcx:no_conn | <<mdcx_mdcx:no_conn>> | endpoint specified in MDCX command has no active connections.
 | 
				
			||||||
 | 
					| mdcx:callid | <<mdcx_mdcx:callid>> | invalid CallId specified in MDCX command.
 | 
				
			||||||
 | 
					| mdcx:connid | <<mdcx_mdcx:connid>> | invalid connection ID specified in MDCX command.
 | 
				
			||||||
 | 
					| crcx:unhandled_param | <<mdcx_crcx:unhandled_param>> | unhandled parameter in MDCX command.
 | 
				
			||||||
 | 
					| mdcx:no_connid | <<mdcx_mdcx:no_connid>> | no connection ID specified in MDCX command.
 | 
				
			||||||
 | 
					| mdcx:conn_not_found | <<mdcx_mdcx:conn_not_found>> | connection specified in MDCX command does not exist.
 | 
				
			||||||
 | 
					| mdcx:invalid_mode | <<mdcx_mdcx:invalid_mode>> | invalid connection mode in MDCX command.
 | 
				
			||||||
 | 
					| mdcx:conn_opt | <<mdcx_mdcx:conn_opt>> | connection options invalid.
 | 
				
			||||||
 | 
					| mdcx:no_remote_conn_desc | <<mdcx_mdcx:no_remote_conn_desc>> | no opposite end specified for connection.
 | 
				
			||||||
 | 
					| mdcx:start_rtp_failure | <<mdcx_mdcx:start_rtp_failure>> | failure to start RTP processing.
 | 
				
			||||||
 | 
					| mdcx:conn_rejected | <<mdcx_mdcx:conn_rejected>> | connection rejected by policy.
 | 
				
			||||||
 | 
					| mdcx:conn_deferred | <<mdcx_mdcx:conn_deferred>> | connection deferred by policy.
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					// rate_ctr_group table crxc statistics
 | 
				
			||||||
 | 
					.crcx - crxc statistics
 | 
				
			||||||
 | 
					[options="header"]
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					| Name | Reference | Description
 | 
				
			||||||
 | 
					| crcx:success | <<crcx_crcx:success>> | CRCX command processed successfully.
 | 
				
			||||||
 | 
					| crcx:bad_action | <<crcx_crcx:bad_action>> | bad action in CRCX command.
 | 
				
			||||||
 | 
					| crcx:unhandled_param | <<crcx_crcx:unhandled_param>> | unhandled parameter in CRCX command.
 | 
				
			||||||
 | 
					| crcx:missing_callid | <<crcx_crcx:missing_callid>> | missing CallId in CRCX command.
 | 
				
			||||||
 | 
					| crcx:invalid_mode | <<crcx_crcx:invalid_mode>> | invalid connection mode in CRCX command.
 | 
				
			||||||
 | 
					| crcx:limit_exceeded | <<crcx_crcx:limit_exceeded>> | limit of concurrent connections was reached.
 | 
				
			||||||
 | 
					| crcx:unkown_callid | <<crcx_crcx:unkown_callid>> | unknown CallId in CRCX command.
 | 
				
			||||||
 | 
					| crcx:alloc_conn_fail | <<crcx_crcx:alloc_conn_fail>> | connection allocation failure.
 | 
				
			||||||
 | 
					| crcx:no_remote_conn_desc | <<crcx_crcx:no_remote_conn_desc>> | no opposite end specified for connection.
 | 
				
			||||||
 | 
					| crcx:start_rtp_failure | <<crcx_crcx:start_rtp_failure>> | failure to start RTP processing.
 | 
				
			||||||
 | 
					| crcx:conn_rejected | <<crcx_crcx:conn_rejected>> | connection rejected by policy.
 | 
				
			||||||
 | 
					| crcx:no_osmux | <<crcx_crcx:no_osmux>> | no osmux offered by peer.
 | 
				
			||||||
 | 
					| crcx:conn_opt | <<crcx_crcx:conn_opt>> | connection options invalid.
 | 
				
			||||||
 | 
					| crcx:codec_nego | <<crcx_crcx:codec_nego>> | codec negotiation failure.
 | 
				
			||||||
 | 
					| crcx:bind_port | <<crcx_crcx:bind_port>> | port bind failure.
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					== Osmo Stat Items
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// generating tables for osmo_stat_items
 | 
				
			||||||
 | 
					== Osmo Counters
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// generating tables for osmo_counters
 | 
				
			||||||
 | 
					// there are no ungrouped osmo_counters
 | 
				
			||||||
							
								
								
									
										94
									
								
								doc/manuals/chapters/mgcp_endpoints.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								doc/manuals/chapters/mgcp_endpoints.adoc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,94 @@
 | 
				
			|||||||
 | 
					== MGCP Endpoints
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MGCP organizes the switching resources in so called endpoints. Each endpoint is
 | 
				
			||||||
 | 
					referenced by its unique identifier. While RFC 3435 specifies a naming scheme, the
 | 
				
			||||||
 | 
					actual identifier naming is subject to the implementation and configuration.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== RTP proxy / RTP bridge endpoints
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OsmoMGW implements a freely configurable number of `rtpbridge` endpoints. Those
 | 
				
			||||||
 | 
					endpoints are able to host two connections at a time to model the functionality
 | 
				
			||||||
 | 
					of a tandem switch.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RTP bridge endpoint identifiers are referenced by the string `rtpbridge/`, a
 | 
				
			||||||
 | 
					hexadecimal number without leading zeros and a domain name (configurable).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					rtpbridge/<number>@<domain>
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.Example: List of virtual endpoints
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					rtpbridge/1@mgw
 | 
				
			||||||
 | 
					rtpbridge/2@mgw
 | 
				
			||||||
 | 
					rtpbridge/3@mgw
 | 
				
			||||||
 | 
					rtpbridge/4@mgw
 | 
				
			||||||
 | 
					rtpbridge/5@mgw
 | 
				
			||||||
 | 
					rtpbridge/6@mgw
 | 
				
			||||||
 | 
					rtpbridge/7@mgw
 | 
				
			||||||
 | 
					rtpbridge/8@mgw
 | 
				
			||||||
 | 
					rtpbridge/9@mgw
 | 
				
			||||||
 | 
					rtpbridge/a@mgw
 | 
				
			||||||
 | 
					rtpbridge/b@mgw
 | 
				
			||||||
 | 
					rtpbridge/c@mgw
 | 
				
			||||||
 | 
					rtpbridge/d@mgw
 | 
				
			||||||
 | 
					rtpbridge/e@mgw
 | 
				
			||||||
 | 
					rtpbridge/f@mgw
 | 
				
			||||||
 | 
					rtpbridge/10@mgw
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== E1/T1 endpoints
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OsmoMGW supports E1 subslot multiplexing as specified by I.460. All possible
 | 
				
			||||||
 | 
					subslot combinations are mapped on individual endpoints. The endpoint names
 | 
				
			||||||
 | 
					are prefixed with `ds/e1-` followed by the trunk number and the E1 timeslot.
 | 
				
			||||||
 | 
					The subslot is defined by a bit rate and a bit offset.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					ds/e1-<trunk>/s-<timeslot>/su<bitrate>-<bitoffset>@<domain>
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.Example: List of endpoints on E1 trunk 0 at E1 timeslot 2
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					ds/e1-0/s-2/su64-0@mgw
 | 
				
			||||||
 | 
					ds/e1-0/s-2/su32-0@mgw
 | 
				
			||||||
 | 
					ds/e1-0/s-2/su32-4@mgw
 | 
				
			||||||
 | 
					ds/e1-0/s-2/su16-0@mgw
 | 
				
			||||||
 | 
					ds/e1-0/s-2/su16-2@mgw
 | 
				
			||||||
 | 
					ds/e1-0/s-2/su16-4@mgw
 | 
				
			||||||
 | 
					ds/e1-0/s-2/su16-6@mgw
 | 
				
			||||||
 | 
					ds/e1-0/s-2/su8-0@mgw
 | 
				
			||||||
 | 
					ds/e1-0/s-2/su8-1@mgw
 | 
				
			||||||
 | 
					ds/e1-0/s-2/su8-2@mgw
 | 
				
			||||||
 | 
					ds/e1-0/s-2/su8-3@mgw
 | 
				
			||||||
 | 
					ds/e1-0/s-2/su8-4@mgw
 | 
				
			||||||
 | 
					ds/e1-0/s-2/su8-5@mgw
 | 
				
			||||||
 | 
					ds/e1-0/s-2/su8-6@mgw
 | 
				
			||||||
 | 
					ds/e1-0/s-2/su8-7@mgw
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When creating connections on endpoints that reside in one E1 timeslot the call
 | 
				
			||||||
 | 
					agent must make sure that no overlapping endpoints are used. It is for example
 | 
				
			||||||
 | 
					not possible to use `ds/e1-0/s-2/su16-2@mgw` and `ds/e1-0/s-2/su8-3@mgw` at the
 | 
				
			||||||
 | 
					same time because they overlap.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.Subslot overlapping
 | 
				
			||||||
 | 
					[options="header"]
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					| Bit offset  4+| Subslots
 | 
				
			||||||
 | 
					| 0 | 8k .2+| 16k .4+| 32k .8+| 64k
 | 
				
			||||||
 | 
					| 1 | 8k
 | 
				
			||||||
 | 
					| 2 | 8k .2+| 16k
 | 
				
			||||||
 | 
					| 3 | 8k
 | 
				
			||||||
 | 
					| 4 | 8k .2+| 16k .4+| 32k
 | 
				
			||||||
 | 
					| 5 | 8k
 | 
				
			||||||
 | 
					| 6 | 8k .2+| 16k
 | 
				
			||||||
 | 
					| 7 | 8k
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NOTE: The current implementation (December 2020) only implements TRAU frame
 | 
				
			||||||
 | 
					encoding/decoding for 16K and 8K subslots. Endpoints with other bitrates are
 | 
				
			||||||
 | 
					not yet useable.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NOTE: the VTY command "show mgcp" can be used to get a list of all available
 | 
				
			||||||
 | 
					endpoints (including identifiers)
 | 
				
			||||||
							
								
								
									
										72
									
								
								doc/manuals/chapters/mgcp_extensions.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								doc/manuals/chapters/mgcp_extensions.adoc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,72 @@
 | 
				
			|||||||
 | 
					== MGCP Extensions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The MGCP protocol is extendable. The following non-standard extensions are
 | 
				
			||||||
 | 
					understood by OsmoMGW.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== `X-Osmo-IGN`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`X-Osmo-IGN` indicates to OsmoMGW that specific items of an endpoint should be
 | 
				
			||||||
 | 
					ignored, so that it is lenient on mismatching values that would normally
 | 
				
			||||||
 | 
					indicate collisions or configuration errors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					==== `X-Osmo-IGN` Format
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The value part of `X-Osmo-IGN` must be one or more items separated by one or more
 | 
				
			||||||
 | 
					spaces. Each item consists of one or more non-whitespace characters.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.Example: `X-Osmo-IGN` format with three ficticious items "X", "abc" and "123".
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					X-Osmo-IGN: X abc 123
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`X-Osmo-IGN` must be issued in the MGCP header section (typically as its last item),
 | 
				
			||||||
 | 
					before the SDP section starts.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					==== Supported `X-Osmo-IGN` Items
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Currently, the following `X-Osmo-IGN` items are supported:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `C`: ignore CallID mismatches, i.e. differing "C" values between connections
 | 
				
			||||||
 | 
					  on the same endpoint.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.Note:
 | 
				
			||||||
 | 
					`X-Osmo-IGN` does not support ignoring mismatches on the domain part of
 | 
				
			||||||
 | 
					an endpoint name, e.g. ignoring a mismatch on "example.com" in
 | 
				
			||||||
 | 
					`rtpbridge/123abc@example.com`. Instead, you may globally configure OsmoMGW
 | 
				
			||||||
 | 
					with `mgcp` / `domain *` to permit all domain parts.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					===== `X-Osmo-IGN: C`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					By default, OsmoMGW verifies that all CallIDs ("C" values) match for all
 | 
				
			||||||
 | 
					connections on any one given endpoint. To ignore CallID mismatches, pass a `C`
 | 
				
			||||||
 | 
					in the `X-Osmo-IGN` header, for the first or the second `CRCX` on an endpoint.
 | 
				
			||||||
 | 
					When the `X-Osmo-IGN: C` is sent for any one `CRCX` on an endpoint, CallID
 | 
				
			||||||
 | 
					mismatches will be ignored for that and all subsequent messages for that
 | 
				
			||||||
 | 
					endpoint. Hence this header only needs to be included once per endpoint, in any
 | 
				
			||||||
 | 
					`CRCX` message that precedes or coincides with a CallID mismatch.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is particularly useful for a BSC that is connected to an A/SCCPlite MSC,
 | 
				
			||||||
 | 
					where the BSC and MSC each are expected to configure their respective own
 | 
				
			||||||
 | 
					connection on a shared endpoint. For A/SCCPlite, it is impossible for the BSC
 | 
				
			||||||
 | 
					to know the CallID that the MSC will use, so CallID mismatches are inevitable.
 | 
				
			||||||
 | 
					See also OsmoBSC, which will by default pass the `X-Osmo-IGN: C` header for
 | 
				
			||||||
 | 
					endpoints associated with an A/SCCPlite MSC.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.Example: `CRCX` message that instructs OsmoMGW to ignore CallID mismatches
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					CRCX 2 rtpbridge/123abc@mgw MGCP 1.0
 | 
				
			||||||
 | 
					M: recvonly
 | 
				
			||||||
 | 
					C: 2
 | 
				
			||||||
 | 
					L: p:20
 | 
				
			||||||
 | 
					X-Osmo-IGN: C
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					v=0
 | 
				
			||||||
 | 
					c=IN IP4 123.12.12.123
 | 
				
			||||||
 | 
					m=audio 5904 RTP/AVP 97
 | 
				
			||||||
 | 
					a=rtpmap:97 GSM-EFR/8000
 | 
				
			||||||
 | 
					a=ptime:40
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== `X-Osmux`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					See <<mgcp-extension-osmux>>
 | 
				
			||||||
							
								
								
									
										115
									
								
								doc/manuals/chapters/overview.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								doc/manuals/chapters/overview.adoc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,115 @@
 | 
				
			|||||||
 | 
					[[overview]]
 | 
				
			||||||
 | 
					== Overview
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This manual should help you getting started with OsmoMGW. It will cover
 | 
				
			||||||
 | 
					aspects of configuring and running the media gateway.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[intro_overview]]
 | 
				
			||||||
 | 
					=== About OsmoMGW
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OsmoMGW is the Osmocom implementation of a media gateway to handle user
 | 
				
			||||||
 | 
					plane (voice) traffic in cellular networks. It can connect and optionally
 | 
				
			||||||
 | 
					transcode RTP voice streams between different network elements such as BTSs
 | 
				
			||||||
 | 
					and external entities like SIP. It is typically co-located with both OsmoBSC
 | 
				
			||||||
 | 
					and OsmoMSC and controlled by them via MGCP, the Media Gateway Control
 | 
				
			||||||
 | 
					Protocol.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[fig-bsc]]
 | 
				
			||||||
 | 
					.OsmoMGW used with OsmoBSC
 | 
				
			||||||
 | 
					[graphviz]
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					digraph G {
 | 
				
			||||||
 | 
					    rankdir = LR;
 | 
				
			||||||
 | 
					    OsmoBTS -> OsmoBSC [label="Abis/IP"];
 | 
				
			||||||
 | 
					    OsmoBSC -> "core-network" [label="3GPP AoIP"];
 | 
				
			||||||
 | 
					    OsmoBSC -> OsmoMGW [label="MGCP"];
 | 
				
			||||||
 | 
					    OsmoBTS -> OsmoMGW [label="RTP",dir=both];
 | 
				
			||||||
 | 
					    OsmoMGW -> "core-network" [label="RTP",dir=both];
 | 
				
			||||||
 | 
					    {rank=same OsmoBSC OsmoMGW}
 | 
				
			||||||
 | 
					    OsmoMGW [color=red];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[fig-msc]]
 | 
				
			||||||
 | 
					.OsmoMGW used with OsmoMSC
 | 
				
			||||||
 | 
					[graphviz]
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					digraph G {
 | 
				
			||||||
 | 
					    rankdir = LR;
 | 
				
			||||||
 | 
					    "2G BSS" -> OsmoMSC [label="3GPP AoIP"];
 | 
				
			||||||
 | 
					    OsmoMSC -> OsmoMGW [label="MGCP"];
 | 
				
			||||||
 | 
					    "2G BSS" -> OsmoMGW [label="RTP",dir=both];
 | 
				
			||||||
 | 
					    OsmoMSC -> OsmoSIP [label="MNCC"];
 | 
				
			||||||
 | 
					    OsmoSIP -> PBX [label="SIP Trunk"];
 | 
				
			||||||
 | 
					    OsmoMGW -> PBX [label="RTP",dir=both];
 | 
				
			||||||
 | 
					    {rank=same OsmoMSC OsmoMGW}
 | 
				
			||||||
 | 
					    OsmoSIP [label="osmo-sip-connector"];
 | 
				
			||||||
 | 
					    OsmoMGW [color=red];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    hNodeB -> OsmoHNBGW [label="Iuh"];
 | 
				
			||||||
 | 
					    OsmoHNBGW -> OsmoMSC [label="IuCS"];
 | 
				
			||||||
 | 
					    hNodeB -> OsmoMGW [label="RTP",dir=both];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[fig-bsc-e1]]
 | 
				
			||||||
 | 
					.Integration of legacy E1 BTS in AoIP network
 | 
				
			||||||
 | 
					[graphviz]
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					digraph G {
 | 
				
			||||||
 | 
					    rankdir = LR;
 | 
				
			||||||
 | 
					    BTS -> OsmoBSC [label="Abis/E1"];
 | 
				
			||||||
 | 
					    OsmoBSC -> "core-network" [label="3GPP AoIP"];
 | 
				
			||||||
 | 
					    OsmoBSC -> OsmoMGW [label="MGCP"];
 | 
				
			||||||
 | 
					    BTS -> OsmoMGW [label="TRAU/E1",dir=both];
 | 
				
			||||||
 | 
					    OsmoMGW -> "core-network" [label="RTP",dir=both];
 | 
				
			||||||
 | 
					    {rank=same OsmoBSC OsmoMGW}
 | 
				
			||||||
 | 
					    OsmoMGW [color=red];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== Software Components
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OsmoMGW contains a variety of different software components, which we’ll
 | 
				
			||||||
 | 
					quickly describe in this section.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					==== MGCP Implementation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OsmoMGW brings its own MGCP implementation through which OsmoMGW is
 | 
				
			||||||
 | 
					controlled.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The commands implemented are CRCX, MDCX, DLCX and RSIP. The command AUEP is
 | 
				
			||||||
 | 
					implemented as a stub and will simply respond with OK.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					==== RTP implementation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Support for IuUP which is used in 3G cells is quite lacking at the moment.
 | 
				
			||||||
 | 
					3G<->3G and 2G<->2G calls should work, but 3G<->2G does not.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					==== Audio transcoder
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Transcoding is currently not supported in OsmoMGW.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== Limitations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					At the moment (November 2020), OsmoMGW implements RTP proxy / RTP bridge
 | 
				
			||||||
 | 
					type endpoints and E1/T1 16k/8k sub-slots with TRAU frames for classic BTS
 | 
				
			||||||
 | 
					support. To the RTP proxy / RTP bridge endpoints two RTP connections can
 | 
				
			||||||
 | 
					be established, which then work as a tandem. E1/T1 endpoints support one
 | 
				
			||||||
 | 
					RTP connection at a time that is associated with a sub-slot on an E1 line.
 | 
				
			||||||
 | 
					We are planning to add further endpoint types for:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- classic E1/T1 timeslots (64kBps alaw/ulaw)
 | 
				
			||||||
 | 
					- announcement/playout end-points
 | 
				
			||||||
 | 
					- conference endpoints
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== Additional resources
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can find the OsmoMGW issue tracker and wiki online at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- https://osmocom.org/projects/osmomgw
 | 
				
			||||||
 | 
					- https://osmocom.org/projects/osmomgw/wiki
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RFC 3435 for MGCP is located at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- https://tools.ietf.org/html/rfc3435
 | 
				
			||||||
							
								
								
									
										42
									
								
								doc/manuals/chapters/qos-example.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								doc/manuals/chapters/qos-example.adoc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
				
			|||||||
 | 
					==== Full example of QoS for osmo-mgw
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In the below example we will show the full set of configuration required
 | 
				
			||||||
 | 
					for both DSCP and PCP differentiation of RTP traffic by osmo-mgw.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					What we want to achieve in this example is the following configuration:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.DSCP and PCP assignments for osmo-mgw Abis downlink traffic in this example
 | 
				
			||||||
 | 
					[options="header",width="30%",cols="2,1,1"]
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					|Traffic      |DSCP|PCP
 | 
				
			||||||
 | 
					|RTP    |  46|  6
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					. configure the osmo-mgw program to set the DSCP value
 | 
				
			||||||
 | 
					. configure an egrees QoS map to map from priority to PCP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.Example Step 1: add related VTY configuration to `osmo-mgw.cfg`
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					...
 | 
				
			||||||
 | 
					mgcp
 | 
				
			||||||
 | 
					 rtp ip-dscp 46
 | 
				
			||||||
 | 
					 rtp socket-priority 6
 | 
				
			||||||
 | 
					...
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.Example Step 2: egress QoS map to map from socket priority to PCP values
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					$ sudo ip link set dev eth0.9<1> type vlan egress-qos-map 0:0 5:5 6:6 7:7 <2>
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					<1> make sure to specify your specific VLAN interface name here instead of `eth0.9`.
 | 
				
			||||||
 | 
					<2> create a egress QoS map that maps the priority value 1:1 to the PCP. We also include the
 | 
				
			||||||
 | 
					    mapping 5:5 and 7:7 from the osmo-bsc example (see <<userman-osmobsc>>) here.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NOTE:: The settings of the `ip` command are volatile and only active until
 | 
				
			||||||
 | 
					the next reboot (or the network device or VLAN is removed).  Please refer to
 | 
				
			||||||
 | 
					the documentation of your specific Linux distribution in order to find out how
 | 
				
			||||||
 | 
					to make such settings persistent by means of an `ifup` hook whenever the interface
 | 
				
			||||||
 | 
					comes up.  For CentOS/RHEL 8 this can e.g. be achieved by means of an `/sbin/ifup-local
 | 
				
			||||||
 | 
					script` (when using `network-scripts` and not NetworkManager).  For Debian or Ubuntu,
 | 
				
			||||||
 | 
					this typically involves adding `up` lines to `/etc/network/interfaces` or a `/etc/network/if-up.d`
 | 
				
			||||||
 | 
					script.
 | 
				
			||||||
							
								
								
									
										25
									
								
								doc/manuals/chapters/running.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								doc/manuals/chapters/running.adoc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					== Running OsmoMGW
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The OsmoMGW executable (`osmo-mgw`) offers the following command-line
 | 
				
			||||||
 | 
					arguments:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== SYNOPSIS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*osmo-mgw* [-h|-V] [-D] [-c 'CONFIGFILE'] [-s]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== OPTIONS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*-h, --help*::
 | 
				
			||||||
 | 
						Print a short help message about the supported options
 | 
				
			||||||
 | 
					*-V, --version*::
 | 
				
			||||||
 | 
						Print the compile-time version number of the program
 | 
				
			||||||
 | 
					*-D, --daemonize*::
 | 
				
			||||||
 | 
						Fork the process as a daemon into background.
 | 
				
			||||||
 | 
					*-c, --config-file 'CONFIGFILE'*::
 | 
				
			||||||
 | 
						Specify the file and path name of the configuration file to be
 | 
				
			||||||
 | 
						used. If none is specified, use `osmo-mgw.cfg` in the current
 | 
				
			||||||
 | 
						working directory.
 | 
				
			||||||
 | 
					*-s, --disable-color*::
 | 
				
			||||||
 | 
						Disable colors for logging to stderr. This has mostly been
 | 
				
			||||||
 | 
						deprecated by VTY based logging configuration, see <<logging>>
 | 
				
			||||||
 | 
						for more information.
 | 
				
			||||||
							
								
								
									
										47
									
								
								doc/manuals/osmomgw-usermanual-docinfo.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								doc/manuals/osmomgw-usermanual-docinfo.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					<revhistory>
 | 
				
			||||||
 | 
					  <revision>
 | 
				
			||||||
 | 
					    <revnumber>1</revnumber>
 | 
				
			||||||
 | 
					    <date>July 24th, 2018</date>
 | 
				
			||||||
 | 
					    <authorinitials>DW</authorinitials>
 | 
				
			||||||
 | 
					    <revremark>
 | 
				
			||||||
 | 
					      Initial version
 | 
				
			||||||
 | 
					    </revremark>
 | 
				
			||||||
 | 
					  </revision>
 | 
				
			||||||
 | 
					</revhistory>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<authorgroup>
 | 
				
			||||||
 | 
					  <author>
 | 
				
			||||||
 | 
					    <firstname>Daniel</firstname>
 | 
				
			||||||
 | 
					    <surname>Willmann</surname>
 | 
				
			||||||
 | 
					    <email>dwillmann@sysmocom.de</email>
 | 
				
			||||||
 | 
					    <authorinitials>DW</authorinitials>
 | 
				
			||||||
 | 
					    <affiliation>
 | 
				
			||||||
 | 
					      <shortaffil>sysmocom</shortaffil>
 | 
				
			||||||
 | 
					      <orgname>sysmocom - s.f.m.c. GmbH</orgname>
 | 
				
			||||||
 | 
					    </affiliation>
 | 
				
			||||||
 | 
					  </author>
 | 
				
			||||||
 | 
					</authorgroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<copyright>
 | 
				
			||||||
 | 
					  <year>2018</year>
 | 
				
			||||||
 | 
					  <holder>sysmocom - s.f.m.c. GmbH</holder>
 | 
				
			||||||
 | 
					</copyright>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<legalnotice>
 | 
				
			||||||
 | 
					  <para>
 | 
				
			||||||
 | 
						Permission is granted to copy, distribute and/or modify this
 | 
				
			||||||
 | 
						document under the terms of the GNU Free Documentation License,
 | 
				
			||||||
 | 
						Version 1.3 or any later version published by the Free Software
 | 
				
			||||||
 | 
						Foundation; with the Invariant Sections being just 'Foreword',
 | 
				
			||||||
 | 
						'Acknowledgements' and 'Preface', with no Front-Cover Texts,
 | 
				
			||||||
 | 
						and no Back-Cover Texts.  A copy of the license is included in
 | 
				
			||||||
 | 
						the section entitled "GNU Free Documentation License".
 | 
				
			||||||
 | 
					  </para>
 | 
				
			||||||
 | 
					  <para>
 | 
				
			||||||
 | 
						The Asciidoc source code of this manual can be found at
 | 
				
			||||||
 | 
						<ulink url="http://git.osmocom.org/osmo-gsm-manuals/">
 | 
				
			||||||
 | 
							http://git.osmocom.org/osmo-gsm-manuals/
 | 
				
			||||||
 | 
						</ulink>
 | 
				
			||||||
 | 
					  </para>
 | 
				
			||||||
 | 
					</legalnotice>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										39
									
								
								doc/manuals/osmomgw-usermanual.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								doc/manuals/osmomgw-usermanual.adoc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					:gfdl-enabled:
 | 
				
			||||||
 | 
					:program-name: OsmoMGW
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OsmoMGW User Manual
 | 
				
			||||||
 | 
					====================
 | 
				
			||||||
 | 
					Daniel Willmann <dwillmann@sysmocom.de>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::./common/chapters/preface.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::{srcdir}/chapters/overview.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::{srcdir}/chapters/running.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::./common/chapters/vty.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::./common/chapters/logging.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::{srcdir}/chapters/configuration.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::{srcdir}/chapters/mgcp_endpoints.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::{srcdir}/chapters/mgcp_extensions.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::./common/chapters/osmux/osmux.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::./common/chapters/qos-dscp-pcp.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//include::{srcdir}/chapters/counters.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::./common/chapters/vty_cpu_sched.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::./common/chapters/port_numbers.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::./common/chapters/bibliography.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::./common/chapters/glossary.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::./common/chapters/gfdl.adoc[]
 | 
				
			||||||
							
								
								
									
										38
									
								
								doc/manuals/osmomgw-vty-reference.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								doc/manuals/osmomgw-vty-reference.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					  ex:ts=2:sw=42sts=2:et
 | 
				
			||||||
 | 
					  -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML 5.0//EN"
 | 
				
			||||||
 | 
					"http://docbook.org/xml/5.0/dtd/docbook.dtd" [
 | 
				
			||||||
 | 
					<!ENTITY chapter-vty      SYSTEM      "./common/chapters/vty.xml" >
 | 
				
			||||||
 | 
					<!ENTITY sections-vty     SYSTEM      "generated/docbook_vty.xml"  >
 | 
				
			||||||
 | 
					]>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<book>
 | 
				
			||||||
 | 
					  <info>
 | 
				
			||||||
 | 
					    <revhistory>
 | 
				
			||||||
 | 
					        <revision>
 | 
				
			||||||
 | 
					            <revnumber>v1</revnumber>
 | 
				
			||||||
 | 
					            <date>12th December 2017</date>
 | 
				
			||||||
 | 
					            <authorinitials>pm</authorinitials>
 | 
				
			||||||
 | 
					            <revremark>Initial</revremark>
 | 
				
			||||||
 | 
					        </revision>
 | 
				
			||||||
 | 
					    </revhistory>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <title>OsmoMGW VTY Reference</title>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <copyright>
 | 
				
			||||||
 | 
					      <year>2017</year>
 | 
				
			||||||
 | 
					    </copyright>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <legalnotice>
 | 
				
			||||||
 | 
					      <para>This work is copyright by <orgname>sysmocom - s.f.m.c. GmbH</orgname>. All rights reserved.
 | 
				
			||||||
 | 
					      </para>
 | 
				
			||||||
 | 
					    </legalnotice>
 | 
				
			||||||
 | 
					  </info>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <!-- Main chapters-->
 | 
				
			||||||
 | 
					  &chapter-vty;
 | 
				
			||||||
 | 
					</book>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										17
									
								
								doc/manuals/regen_doc.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										17
									
								
								doc/manuals/regen_doc.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					#!/bin/sh -x
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [ -z "$DOCKER_PLAYGROUND" ]; then
 | 
				
			||||||
 | 
						echo "You need to set DOCKER_PLAYGROUND"
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SCRIPT=$(realpath "$0")
 | 
				
			||||||
 | 
					MANUAL_DIR=$(dirname "$SCRIPT")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					COMMIT=${COMMIT:-$(git log -1 --format=format:%H)}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cd "$DOCKER_PLAYGROUND/scripts" || exit 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OSMO_MGW_BRANCH=$COMMIT ./regen_doc.sh osmo-mgw 4243 \
 | 
				
			||||||
 | 
						"$MANUAL_DIR/chapters/counters_generated.adoc" \
 | 
				
			||||||
 | 
						"$MANUAL_DIR/vty/mgw_vty_reference.xml"
 | 
				
			||||||
							
								
								
									
										2
									
								
								doc/manuals/vty/mgw_vty_additions.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								doc/manuals/vty/mgw_vty_additions.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					<vtydoc xmlns='urn:osmocom:xml:libosmocore:vty:doc:1.0'>
 | 
				
			||||||
 | 
					</vtydoc>
 | 
				
			||||||
@@ -92,8 +92,8 @@ fi
 | 
				
			|||||||
if test -n "$v"
 | 
					if test -n "$v"
 | 
				
			||||||
then
 | 
					then
 | 
				
			||||||
    : # use $v
 | 
					    : # use $v
 | 
				
			||||||
elif test -d ./.git \
 | 
					elif
 | 
				
			||||||
    && v=`git describe --abbrev=4 --match='v*' HEAD 2>/dev/null \
 | 
					       v=`git describe --abbrev=4 --match='v*' HEAD 2>/dev/null \
 | 
				
			||||||
	  || git describe --abbrev=4 HEAD 2>/dev/null` \
 | 
						  || git describe --abbrev=4 HEAD 2>/dev/null` \
 | 
				
			||||||
    && case $v in
 | 
					    && case $v in
 | 
				
			||||||
	 [0-9]*) ;;
 | 
						 [0-9]*) ;;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,13 +3,17 @@ SUBDIRS = \
 | 
				
			|||||||
	$(NULL)
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nobase_include_HEADERS = \
 | 
					nobase_include_HEADERS = \
 | 
				
			||||||
	osmocom/legacy_mgcp/mgcp.h \
 | 
					 | 
				
			||||||
	osmocom/legacy_mgcp/mgcp_internal.h \
 | 
					 | 
				
			||||||
	osmocom/legacy_mgcp/osmux.h \
 | 
					 | 
				
			||||||
	osmocom/mgcp_client/mgcp_client.h \
 | 
						osmocom/mgcp_client/mgcp_client.h \
 | 
				
			||||||
	osmocom/mgcp_client/mgcp_common.h \
 | 
						osmocom/mgcp_client/mgcp_client_endpoint_fsm.h \
 | 
				
			||||||
 | 
						osmocom/mgcp_client/mgcp_client_fsm.h \
 | 
				
			||||||
 | 
						osmocom/mgcp_client/mgcp_client_pool.h \
 | 
				
			||||||
	osmocom/mgcp/mgcp.h \
 | 
						osmocom/mgcp/mgcp.h \
 | 
				
			||||||
	osmocom/mgcp/mgcp_common.h \
 | 
						osmocom/mgcp/mgcp_common.h \
 | 
				
			||||||
	osmocom/mgcp/mgcp_internal.h \
 | 
					 | 
				
			||||||
	osmocom/mgcp/osmux.h \
 | 
						osmocom/mgcp/osmux.h \
 | 
				
			||||||
	$(NULL)
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# This gets copied during make from osmocom/mgcp/mgcp_common.h. Therefore it is not included in the source tree and we
 | 
				
			||||||
 | 
					# don't need to distribute it (OS#4084).
 | 
				
			||||||
 | 
					nobase_nodist_include_HEADERS = \
 | 
				
			||||||
 | 
						osmocom/mgcp_client/mgcp_common.h \
 | 
				
			||||||
 | 
						$(NULL)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,4 @@
 | 
				
			|||||||
SUBDIRS = \
 | 
					SUBDIRS = \
 | 
				
			||||||
	legacy_mgcp \
 | 
					 | 
				
			||||||
	mgcp_client \
 | 
						mgcp_client \
 | 
				
			||||||
	mgcp \
 | 
						mgcp \
 | 
				
			||||||
	$(NULL)
 | 
						$(NULL)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +0,0 @@
 | 
				
			|||||||
noinst_HEADERS = \
 | 
					 | 
				
			||||||
	mgcp_transcode.h \
 | 
					 | 
				
			||||||
	vty.h \
 | 
					 | 
				
			||||||
	$(NULL)
 | 
					 | 
				
			||||||
@@ -1,292 +0,0 @@
 | 
				
			|||||||
/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
 | 
					 | 
				
			||||||
 * (C) 2009-2012 by On-Waves
 | 
					 | 
				
			||||||
 * All Rights Reserved
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is free software; you can redistribute it and/or modify
 | 
					 | 
				
			||||||
 * it under the terms of the GNU Affero General Public License as published by
 | 
					 | 
				
			||||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
					 | 
				
			||||||
 * (at your option) any later version.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is distributed in the hope that it will be useful,
 | 
					 | 
				
			||||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 | 
				
			||||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					 | 
				
			||||||
 * GNU Affero General Public License for more details.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * You should have received a copy of the GNU Affero General Public License
 | 
					 | 
				
			||||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef OPENBSC_MGCP_H
 | 
					 | 
				
			||||||
#define OPENBSC_MGCP_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <osmocom/core/msgb.h>
 | 
					 | 
				
			||||||
#include <osmocom/core/write_queue.h>
 | 
					 | 
				
			||||||
#include <osmocom/core/timer.h>
 | 
					 | 
				
			||||||
#include <osmocom/core/logging.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <arpa/inet.h>
 | 
					 | 
				
			||||||
#include <sys/types.h>
 | 
					 | 
				
			||||||
#include <sys/socket.h>
 | 
					 | 
				
			||||||
#include <netinet/in.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define RTP_PORT_DEFAULT 4000
 | 
					 | 
				
			||||||
#define RTP_PORT_NET_DEFAULT 16000
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Calculate the RTP audio port for the given multiplex
 | 
					 | 
				
			||||||
 * and the direction. This allows a semi static endpoint
 | 
					 | 
				
			||||||
 * to port calculation removing the need for the BSC
 | 
					 | 
				
			||||||
 * and the MediaGateway to communicate.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Port usage explained:
 | 
					 | 
				
			||||||
 *       base + (multiplex * 2) + 0 == local port to wait for network packets
 | 
					 | 
				
			||||||
 *       base + (multiplex * 2) + 1 == local port for rtcp
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * The above port will receive packets from the BTS that need
 | 
					 | 
				
			||||||
 * to be patched and forwarded to the network.
 | 
					 | 
				
			||||||
 * The above port will receive packets from the network that
 | 
					 | 
				
			||||||
 * need to be patched and forwarded to the BTS.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * We assume to have a static BTS IP address so we can differentiate
 | 
					 | 
				
			||||||
 * network and BTS.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static inline int rtp_calculate_port(int multiplex, int base)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return base + (multiplex * 2);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Handling of MGCP Endpoints and the MGCP Config
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
struct mgcp_endpoint;
 | 
					 | 
				
			||||||
struct mgcp_config;
 | 
					 | 
				
			||||||
struct mgcp_trunk_config;
 | 
					 | 
				
			||||||
struct mgcp_rtp_end;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define MGCP_ENDP_CRCX 1
 | 
					 | 
				
			||||||
#define MGCP_ENDP_DLCX 2
 | 
					 | 
				
			||||||
#define MGCP_ENDP_MDCX 3
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * what to do with the msg?
 | 
					 | 
				
			||||||
 *	- continue as usual?
 | 
					 | 
				
			||||||
 *	- reject and send a failure code?
 | 
					 | 
				
			||||||
 *	- defer? do not send anything
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#define MGCP_POLICY_CONT	4
 | 
					 | 
				
			||||||
#define MGCP_POLICY_REJECT	5
 | 
					 | 
				
			||||||
#define MGCP_POLICY_DEFER	6
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef int (*mgcp_realloc)(struct mgcp_trunk_config *cfg, int endpoint);
 | 
					 | 
				
			||||||
typedef int (*mgcp_change)(struct mgcp_trunk_config *cfg, int endpoint, int state);
 | 
					 | 
				
			||||||
typedef int (*mgcp_policy)(struct mgcp_trunk_config *cfg, int endpoint, int state, const char *transactio_id);
 | 
					 | 
				
			||||||
typedef int (*mgcp_reset)(struct mgcp_trunk_config *cfg);
 | 
					 | 
				
			||||||
typedef int (*mgcp_rqnt)(struct mgcp_endpoint *endp, char tone);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Return:
 | 
					 | 
				
			||||||
 *   <  0 in case no audio was processed
 | 
					 | 
				
			||||||
 *   >= 0 in case audio was processed. The remaining payload
 | 
					 | 
				
			||||||
 *   length will be returned.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
typedef int (*mgcp_processing)(struct mgcp_endpoint *endp,
 | 
					 | 
				
			||||||
			       struct mgcp_rtp_end *dst_end,
 | 
					 | 
				
			||||||
			       char *data, int *len, int buf_size);
 | 
					 | 
				
			||||||
typedef int (*mgcp_processing_setup)(struct mgcp_endpoint *endp,
 | 
					 | 
				
			||||||
				     struct mgcp_rtp_end *dst_end,
 | 
					 | 
				
			||||||
				     struct mgcp_rtp_end *src_end);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef void (*mgcp_get_format)(struct mgcp_endpoint *endp,
 | 
					 | 
				
			||||||
				int *payload_type,
 | 
					 | 
				
			||||||
				const char**subtype_name,
 | 
					 | 
				
			||||||
				const char**fmtp_extra);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define PORT_ALLOC_STATIC	0
 | 
					 | 
				
			||||||
#define PORT_ALLOC_DYNAMIC	1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * This holds information on how to allocate ports
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
struct mgcp_port_range {
 | 
					 | 
				
			||||||
	int mode;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* addr or NULL to fall-back to default */
 | 
					 | 
				
			||||||
	char *bind_addr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* pre-allocated from a base? */
 | 
					 | 
				
			||||||
	int base_port;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* dynamically allocated */
 | 
					 | 
				
			||||||
	int range_start;
 | 
					 | 
				
			||||||
	int range_end;
 | 
					 | 
				
			||||||
	int last_port;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define MGCP_KEEPALIVE_ONCE (-1)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct mgcp_trunk_config {
 | 
					 | 
				
			||||||
	struct llist_head entry;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct mgcp_config *cfg;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int trunk_nr;
 | 
					 | 
				
			||||||
	int trunk_type;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	char *audio_fmtp_extra;
 | 
					 | 
				
			||||||
	char *audio_name;
 | 
					 | 
				
			||||||
	int audio_payload;
 | 
					 | 
				
			||||||
	int audio_send_ptime;
 | 
					 | 
				
			||||||
	int audio_send_name;
 | 
					 | 
				
			||||||
	int audio_loop;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int no_audio_transcoding;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int omit_rtcp;
 | 
					 | 
				
			||||||
	int keepalive_interval;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* RTP patching */
 | 
					 | 
				
			||||||
	int force_constant_ssrc; /* 0: don't, 1: once */
 | 
					 | 
				
			||||||
	int force_aligned_timing;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* spec handling */
 | 
					 | 
				
			||||||
	int force_realloc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* timer */
 | 
					 | 
				
			||||||
	struct osmo_timer_list keepalive_timer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	unsigned int number_endpoints;
 | 
					 | 
				
			||||||
	struct mgcp_endpoint *endpoints;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum mgcp_role {
 | 
					 | 
				
			||||||
	MGCP_BSC = 0,
 | 
					 | 
				
			||||||
	MGCP_BSC_NAT,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum mgcp_connection_mode {
 | 
					 | 
				
			||||||
	MGCP_CONN_NONE = 0,
 | 
					 | 
				
			||||||
	MGCP_CONN_RECV_ONLY = 1,
 | 
					 | 
				
			||||||
	MGCP_CONN_SEND_ONLY = 2,
 | 
					 | 
				
			||||||
	MGCP_CONN_RECV_SEND = MGCP_CONN_RECV_ONLY | MGCP_CONN_SEND_ONLY,
 | 
					 | 
				
			||||||
	MGCP_CONN_LOOPBACK  = 4 | MGCP_CONN_RECV_SEND,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct mgcp_config {
 | 
					 | 
				
			||||||
	int source_port;
 | 
					 | 
				
			||||||
	char *local_ip;
 | 
					 | 
				
			||||||
	char *source_addr;
 | 
					 | 
				
			||||||
	char *bts_ip;
 | 
					 | 
				
			||||||
	char *call_agent_addr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct in_addr bts_in;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* transcoder handling */
 | 
					 | 
				
			||||||
	char *transcoder_ip;
 | 
					 | 
				
			||||||
	struct in_addr transcoder_in;
 | 
					 | 
				
			||||||
	int transcoder_remote_base;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* RTP processing */
 | 
					 | 
				
			||||||
	mgcp_processing rtp_processing_cb;
 | 
					 | 
				
			||||||
	mgcp_processing_setup setup_rtp_processing_cb;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	mgcp_get_format get_net_downlink_format_cb;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct osmo_wqueue gw_fd;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct mgcp_port_range bts_ports;
 | 
					 | 
				
			||||||
	struct mgcp_port_range net_ports;
 | 
					 | 
				
			||||||
	struct mgcp_port_range transcoder_ports;
 | 
					 | 
				
			||||||
	int endp_dscp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int bts_force_ptime;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	mgcp_change change_cb;
 | 
					 | 
				
			||||||
	mgcp_policy policy_cb;
 | 
					 | 
				
			||||||
	mgcp_reset reset_cb;
 | 
					 | 
				
			||||||
	mgcp_realloc realloc_cb;
 | 
					 | 
				
			||||||
	mgcp_rqnt rqnt_cb;
 | 
					 | 
				
			||||||
	void *data;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	uint32_t last_call_id;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* trunk handling */
 | 
					 | 
				
			||||||
	struct mgcp_trunk_config trunk;
 | 
					 | 
				
			||||||
	struct llist_head trunks;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* only used for start with a static configuration */
 | 
					 | 
				
			||||||
	int last_net_port;
 | 
					 | 
				
			||||||
	int last_bts_port;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	enum mgcp_role role;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* osmux translator: 0 means disabled, 1 means enabled */
 | 
					 | 
				
			||||||
	int osmux;
 | 
					 | 
				
			||||||
	/* addr to bind the server to */
 | 
					 | 
				
			||||||
	char *osmux_addr;
 | 
					 | 
				
			||||||
	/* The BSC-NAT may ask for enabling osmux on demand. This tells us if
 | 
					 | 
				
			||||||
	 * the osmux socket is already initialized.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	int osmux_init;
 | 
					 | 
				
			||||||
	/* osmux batch factor: from 1 to 4 maximum */
 | 
					 | 
				
			||||||
	int osmux_batch;
 | 
					 | 
				
			||||||
	/* osmux batch size (in bytes) */
 | 
					 | 
				
			||||||
	int osmux_batch_size;
 | 
					 | 
				
			||||||
	/* osmux port */
 | 
					 | 
				
			||||||
	uint16_t osmux_port;
 | 
					 | 
				
			||||||
	/* Pad circuit with dummy messages until we see the first voice
 | 
					 | 
				
			||||||
	 * message.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	uint16_t osmux_dummy;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* config management */
 | 
					 | 
				
			||||||
struct mgcp_config *mgcp_config_alloc(void);
 | 
					 | 
				
			||||||
int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg,
 | 
					 | 
				
			||||||
		      enum mgcp_role role);
 | 
					 | 
				
			||||||
int mgcp_vty_init(void);
 | 
					 | 
				
			||||||
int mgcp_endpoints_allocate(struct mgcp_trunk_config *cfg);
 | 
					 | 
				
			||||||
void mgcp_release_endp(struct mgcp_endpoint *endp);
 | 
					 | 
				
			||||||
void mgcp_initialize_endp(struct mgcp_endpoint *endp);
 | 
					 | 
				
			||||||
int mgcp_reset_transcoder(struct mgcp_config *cfg);
 | 
					 | 
				
			||||||
void mgcp_format_stats(struct mgcp_endpoint *endp, char *stats, size_t size);
 | 
					 | 
				
			||||||
int mgcp_parse_stats(struct msgb *msg, uint32_t *ps, uint32_t *os, uint32_t *pr, uint32_t *_or, int *loss, uint32_t *jitter);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void mgcp_trunk_set_keepalive(struct mgcp_trunk_config *tcfg, int interval);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * format helper functions
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* adc helper */
 | 
					 | 
				
			||||||
static inline int mgcp_timeslot_to_endpoint(int multiplex, int timeslot)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (timeslot == 0) {
 | 
					 | 
				
			||||||
		LOGP(DLMGCP, LOGL_ERROR, "Timeslot should not be 0\n");
 | 
					 | 
				
			||||||
		timeslot = 255;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return timeslot + (32 * multiplex);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline void mgcp_endpoint_to_timeslot(int endpoint, int *multiplex, int *timeslot)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	*multiplex = endpoint / 32;
 | 
					 | 
				
			||||||
	*timeslot = endpoint % 32;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int mgcp_send_reset_ep(struct mgcp_endpoint *endp, int endpoint);
 | 
					 | 
				
			||||||
int mgcp_send_reset_all(struct mgcp_config *cfg);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int mgcp_create_bind(const char *source_addr, struct osmo_fd *fd, int port);
 | 
					 | 
				
			||||||
int mgcp_send(struct mgcp_endpoint *endp, int dest, int is_rtp, struct sockaddr_in *addr, char *buf, int rc);
 | 
					 | 
				
			||||||
int mgcp_udp_send(int fd, struct in_addr *addr, int port, char *buf, int len);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
@@ -1,337 +0,0 @@
 | 
				
			|||||||
/* MGCP Private Data */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
 | 
					 | 
				
			||||||
 * (C) 2009-2012 by On-Waves
 | 
					 | 
				
			||||||
 * All Rights Reserved
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is free software; you can redistribute it and/or modify
 | 
					 | 
				
			||||||
 * it under the terms of the GNU Affero General Public License as published by
 | 
					 | 
				
			||||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
					 | 
				
			||||||
 * (at your option) any later version.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is distributed in the hope that it will be useful,
 | 
					 | 
				
			||||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 | 
				
			||||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					 | 
				
			||||||
 * GNU Affero General Public License for more details.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * You should have received a copy of the GNU Affero General Public License
 | 
					 | 
				
			||||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#pragma once
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <osmocom/core/select.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define CI_UNUSED 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum mgcp_trunk_type {
 | 
					 | 
				
			||||||
	MGCP_TRUNK_VIRTUAL,
 | 
					 | 
				
			||||||
	MGCP_TRUNK_E1,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct mgcp_rtp_stream_state {
 | 
					 | 
				
			||||||
	uint32_t ssrc;
 | 
					 | 
				
			||||||
	uint16_t last_seq;
 | 
					 | 
				
			||||||
	uint32_t last_timestamp;
 | 
					 | 
				
			||||||
	uint32_t err_ts_counter;
 | 
					 | 
				
			||||||
	int32_t last_tsdelta;
 | 
					 | 
				
			||||||
	uint32_t last_arrival_time;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct mgcp_rtp_state {
 | 
					 | 
				
			||||||
	int initialized;
 | 
					 | 
				
			||||||
	int patch_ssrc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	uint32_t orig_ssrc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int seq_offset;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int32_t  timestamp_offset;
 | 
					 | 
				
			||||||
	uint32_t packet_duration;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct mgcp_rtp_stream_state in_stream;
 | 
					 | 
				
			||||||
	struct mgcp_rtp_stream_state out_stream;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* jitter and packet loss calculation */
 | 
					 | 
				
			||||||
	int stats_initialized;
 | 
					 | 
				
			||||||
	uint16_t stats_base_seq;
 | 
					 | 
				
			||||||
	uint16_t stats_max_seq;
 | 
					 | 
				
			||||||
	uint32_t stats_ssrc;
 | 
					 | 
				
			||||||
	uint32_t stats_jitter;
 | 
					 | 
				
			||||||
	int32_t stats_transit;
 | 
					 | 
				
			||||||
	int stats_cycles;
 | 
					 | 
				
			||||||
	bool patched_first_rtp_payload; /* FIXME: drop this, see OS#2459 */
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct mgcp_rtp_codec {
 | 
					 | 
				
			||||||
	uint32_t rate;
 | 
					 | 
				
			||||||
	int channels;
 | 
					 | 
				
			||||||
	uint32_t frame_duration_num;
 | 
					 | 
				
			||||||
	uint32_t frame_duration_den;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int payload_type;
 | 
					 | 
				
			||||||
	char *audio_name;
 | 
					 | 
				
			||||||
	char *subtype_name;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct mgcp_rtp_end {
 | 
					 | 
				
			||||||
	/* statistics */
 | 
					 | 
				
			||||||
	unsigned int packets;
 | 
					 | 
				
			||||||
	unsigned int octets;
 | 
					 | 
				
			||||||
	unsigned int dropped_packets;
 | 
					 | 
				
			||||||
	struct in_addr addr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* in network byte order */
 | 
					 | 
				
			||||||
	int rtp_port, rtcp_port;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* audio codec information */
 | 
					 | 
				
			||||||
	struct mgcp_rtp_codec codec;
 | 
					 | 
				
			||||||
	struct mgcp_rtp_codec alt_codec; /* TODO/XXX: make it generic */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* per endpoint data */
 | 
					 | 
				
			||||||
	int  frames_per_packet;
 | 
					 | 
				
			||||||
	uint32_t packet_duration_ms;
 | 
					 | 
				
			||||||
	char *fmtp_extra;
 | 
					 | 
				
			||||||
	int output_enabled;
 | 
					 | 
				
			||||||
	int force_output_ptime;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* RTP patching */
 | 
					 | 
				
			||||||
	int force_constant_ssrc; /* -1: always, 0: don't, 1: once */
 | 
					 | 
				
			||||||
	int force_aligned_timing;
 | 
					 | 
				
			||||||
	void *rtp_process_data;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * Each end has a socket...
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	struct osmo_fd rtp;
 | 
					 | 
				
			||||||
	struct osmo_fd rtcp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int local_port;
 | 
					 | 
				
			||||||
	int local_alloc;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum {
 | 
					 | 
				
			||||||
	MGCP_TAP_BTS_IN,
 | 
					 | 
				
			||||||
	MGCP_TAP_BTS_OUT,
 | 
					 | 
				
			||||||
	MGCP_TAP_NET_IN,
 | 
					 | 
				
			||||||
	MGCP_TAP_NET_OUT,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* last element */
 | 
					 | 
				
			||||||
	MGCP_TAP_COUNT
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct mgcp_rtp_tap {
 | 
					 | 
				
			||||||
	int enabled;
 | 
					 | 
				
			||||||
	struct sockaddr_in forward;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct mgcp_lco {
 | 
					 | 
				
			||||||
	char *string;
 | 
					 | 
				
			||||||
	char *codec;
 | 
					 | 
				
			||||||
	int pkt_period_min; /* time in ms */
 | 
					 | 
				
			||||||
	int pkt_period_max; /* time in ms */
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum mgcp_type {
 | 
					 | 
				
			||||||
	MGCP_RTP_DEFAULT	= 0,
 | 
					 | 
				
			||||||
	MGCP_RTP_TRANSCODED,
 | 
					 | 
				
			||||||
	MGCP_OSMUX_BSC,
 | 
					 | 
				
			||||||
	MGCP_OSMUX_BSC_NAT,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <osmocom/legacy_mgcp/osmux.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct mgcp_endpoint {
 | 
					 | 
				
			||||||
	int allocated;
 | 
					 | 
				
			||||||
	uint32_t ci;
 | 
					 | 
				
			||||||
	char *callid;
 | 
					 | 
				
			||||||
	struct mgcp_lco local_options;
 | 
					 | 
				
			||||||
	int conn_mode;
 | 
					 | 
				
			||||||
	int orig_mode;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* backpointer */
 | 
					 | 
				
			||||||
	struct mgcp_config *cfg;
 | 
					 | 
				
			||||||
	struct mgcp_trunk_config *tcfg;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* port status for bts/net */
 | 
					 | 
				
			||||||
	struct mgcp_rtp_end bts_end;
 | 
					 | 
				
			||||||
	struct mgcp_rtp_end net_end;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * For transcoding we will send from the local_port
 | 
					 | 
				
			||||||
	 * of trans_bts and it will arrive at trans_net from
 | 
					 | 
				
			||||||
	 * where we will forward it to the network.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	struct mgcp_rtp_end trans_bts;
 | 
					 | 
				
			||||||
	struct mgcp_rtp_end trans_net;
 | 
					 | 
				
			||||||
	enum mgcp_type type;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* sequence bits */
 | 
					 | 
				
			||||||
	struct mgcp_rtp_state net_state;
 | 
					 | 
				
			||||||
	struct mgcp_rtp_state bts_state;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* fields for re-transmission */
 | 
					 | 
				
			||||||
	char *last_trans;
 | 
					 | 
				
			||||||
	char *last_response;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* tap for the endpoint */
 | 
					 | 
				
			||||||
	struct mgcp_rtp_tap taps[MGCP_TAP_COUNT];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct {
 | 
					 | 
				
			||||||
		/* Osmux state: disabled, activating, active */
 | 
					 | 
				
			||||||
		enum osmux_state state;
 | 
					 | 
				
			||||||
		/* Allocated Osmux circuit ID for this endpoint */
 | 
					 | 
				
			||||||
		int allocated_cid;
 | 
					 | 
				
			||||||
		/* Used Osmux circuit ID for this endpoint */
 | 
					 | 
				
			||||||
		uint8_t cid;
 | 
					 | 
				
			||||||
		/* handle to batch messages */
 | 
					 | 
				
			||||||
		struct osmux_in_handle *in;
 | 
					 | 
				
			||||||
		/* handle to unbatch messages */
 | 
					 | 
				
			||||||
		struct osmux_out_handle out;
 | 
					 | 
				
			||||||
		/* statistics */
 | 
					 | 
				
			||||||
		struct {
 | 
					 | 
				
			||||||
			uint32_t chunks;
 | 
					 | 
				
			||||||
			uint32_t octets;
 | 
					 | 
				
			||||||
		} stats;
 | 
					 | 
				
			||||||
	} osmux;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define for_each_line(line, save)			\
 | 
					 | 
				
			||||||
	for (line = strline_r(NULL, &save); line;\
 | 
					 | 
				
			||||||
	     line = strline_r(NULL, &save))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline char *strline_r(char *str, char **saveptr)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	char *result;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (str)
 | 
					 | 
				
			||||||
		*saveptr = str;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	result = *saveptr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (*saveptr != NULL) {
 | 
					 | 
				
			||||||
		*saveptr = strpbrk(*saveptr, "\r\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (*saveptr != NULL) {
 | 
					 | 
				
			||||||
			char *eos = *saveptr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if ((*saveptr)[0] == '\r' && (*saveptr)[1] == '\n')
 | 
					 | 
				
			||||||
				(*saveptr)++;
 | 
					 | 
				
			||||||
			(*saveptr)++;
 | 
					 | 
				
			||||||
			if ((*saveptr)[0] == '\0')
 | 
					 | 
				
			||||||
				*saveptr = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			*eos = '\0';
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return result;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define ENDPOINT_NUMBER(endp) abs((int)(endp - endp->tcfg->endpoints))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Internal structure while parsing a request
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
struct mgcp_parse_data {
 | 
					 | 
				
			||||||
	struct mgcp_config *cfg;
 | 
					 | 
				
			||||||
	struct mgcp_endpoint *endp;
 | 
					 | 
				
			||||||
	char *trans;
 | 
					 | 
				
			||||||
	char *save;
 | 
					 | 
				
			||||||
	int found;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int mgcp_send_dummy(struct mgcp_endpoint *endp);
 | 
					 | 
				
			||||||
int mgcp_bind_bts_rtp_port(struct mgcp_endpoint *endp, int rtp_port);
 | 
					 | 
				
			||||||
int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port);
 | 
					 | 
				
			||||||
int mgcp_bind_trans_bts_rtp_port(struct mgcp_endpoint *enp, int rtp_port);
 | 
					 | 
				
			||||||
int mgcp_bind_trans_net_rtp_port(struct mgcp_endpoint *enp, int rtp_port);
 | 
					 | 
				
			||||||
int mgcp_free_rtp_port(struct mgcp_rtp_end *end);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* For transcoding we need to manage an in and an output that are connected */
 | 
					 | 
				
			||||||
static inline int endp_back_channel(int endpoint)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return endpoint + 60;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct mgcp_trunk_config *mgcp_trunk_alloc(struct mgcp_config *cfg, int index);
 | 
					 | 
				
			||||||
struct mgcp_trunk_config *mgcp_trunk_num(struct mgcp_config *cfg, int index);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change,
 | 
					 | 
				
			||||||
			 struct mgcp_rtp_end *rtp);
 | 
					 | 
				
			||||||
uint32_t mgcp_rtp_packet_duration(struct mgcp_endpoint *endp,
 | 
					 | 
				
			||||||
				  struct mgcp_rtp_end *rtp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void mgcp_state_calc_loss(struct mgcp_rtp_state *s, struct mgcp_rtp_end *,
 | 
					 | 
				
			||||||
			uint32_t *expected, int *loss);
 | 
					 | 
				
			||||||
uint32_t mgcp_state_calc_jitter(struct mgcp_rtp_state *);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* payload processing default functions */
 | 
					 | 
				
			||||||
int mgcp_rtp_processing_default(struct mgcp_endpoint *endp, struct mgcp_rtp_end *dst_end,
 | 
					 | 
				
			||||||
				char *data, int *len, int buf_size);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int mgcp_setup_rtp_processing_default(struct mgcp_endpoint *endp,
 | 
					 | 
				
			||||||
				      struct mgcp_rtp_end *dst_end,
 | 
					 | 
				
			||||||
				      struct mgcp_rtp_end *src_end);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void mgcp_get_net_downlink_format_default(struct mgcp_endpoint *endp,
 | 
					 | 
				
			||||||
					  int *payload_type,
 | 
					 | 
				
			||||||
					  const char**subtype_name,
 | 
					 | 
				
			||||||
					  const char**fmtp_extra);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* internal RTP Annex A counting */
 | 
					 | 
				
			||||||
void mgcp_rtp_annex_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *state,
 | 
					 | 
				
			||||||
			const uint16_t seq, const int32_t transit,
 | 
					 | 
				
			||||||
			const uint32_t ssrc);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int mgcp_set_ip_tos(int fd, int tos);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum {
 | 
					 | 
				
			||||||
	MGCP_DEST_NET = 0,
 | 
					 | 
				
			||||||
	MGCP_DEST_BTS,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define MGCP_DUMMY_LOAD 0x23
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * SDP related information
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
/* Assume audio frame length of 20ms */
 | 
					 | 
				
			||||||
#define DEFAULT_RTP_AUDIO_FRAME_DUR_NUM 20
 | 
					 | 
				
			||||||
#define DEFAULT_RTP_AUDIO_FRAME_DUR_DEN 1000
 | 
					 | 
				
			||||||
#define DEFAULT_RTP_AUDIO_PACKET_DURATION_MS 20
 | 
					 | 
				
			||||||
#define DEFAULT_RTP_AUDIO_DEFAULT_RATE  8000
 | 
					 | 
				
			||||||
#define DEFAULT_RTP_AUDIO_DEFAULT_CHANNELS 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define PTYPE_UNDEFINED (-1)
 | 
					 | 
				
			||||||
int mgcp_parse_sdp_data(struct mgcp_endpoint *endp, struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p);
 | 
					 | 
				
			||||||
int mgcp_set_audio_info(void *ctx, struct mgcp_rtp_codec *codec,
 | 
					 | 
				
			||||||
			int payload_type, const char *audio_name);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Internal network related
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static inline const char *mgcp_net_src_addr(struct mgcp_endpoint *endp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (endp->cfg->net_ports.bind_addr)
 | 
					 | 
				
			||||||
		return endp->cfg->net_ports.bind_addr;
 | 
					 | 
				
			||||||
	return endp->cfg->source_addr;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline const char *mgcp_bts_src_addr(struct mgcp_endpoint *endp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (endp->cfg->bts_ports.bind_addr)
 | 
					 | 
				
			||||||
		return endp->cfg->bts_ports.bind_addr;
 | 
					 | 
				
			||||||
	return endp->cfg->source_addr;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int mgcp_msg_terminate_nul(struct msgb *msg);
 | 
					 | 
				
			||||||
@@ -1,90 +0,0 @@
 | 
				
			|||||||
/*
 | 
					 | 
				
			||||||
 * (C) 2014 by On-Waves
 | 
					 | 
				
			||||||
 * All Rights Reserved
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is free software; you can redistribute it and/or modify
 | 
					 | 
				
			||||||
 * it under the terms of the GNU Affero General Public License as published by
 | 
					 | 
				
			||||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
					 | 
				
			||||||
 * (at your option) any later version.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is distributed in the hope that it will be useful,
 | 
					 | 
				
			||||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 | 
				
			||||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					 | 
				
			||||||
 * GNU Affero General Public License for more details.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * You should have received a copy of the GNU Affero General Public License
 | 
					 | 
				
			||||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#ifndef OPENBSC_MGCP_TRANSCODE_H
 | 
					 | 
				
			||||||
#define OPENBSC_MGCP_TRANSCODE_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "bscconfig.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <gsm.h>
 | 
					 | 
				
			||||||
#ifdef HAVE_BCG729
 | 
					 | 
				
			||||||
#include <bcg729/decoder.h>
 | 
					 | 
				
			||||||
#include <bcg729/encoder.h>
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum audio_format {
 | 
					 | 
				
			||||||
	AF_INVALID,
 | 
					 | 
				
			||||||
	AF_S16,
 | 
					 | 
				
			||||||
	AF_L16,
 | 
					 | 
				
			||||||
	AF_GSM,
 | 
					 | 
				
			||||||
	AF_G729,
 | 
					 | 
				
			||||||
	AF_PCMA,
 | 
					 | 
				
			||||||
	AF_PCMU
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct mgcp_process_rtp_state {
 | 
					 | 
				
			||||||
	/* decoding */
 | 
					 | 
				
			||||||
	enum audio_format src_fmt;
 | 
					 | 
				
			||||||
	union {
 | 
					 | 
				
			||||||
		gsm gsm_handle;
 | 
					 | 
				
			||||||
#ifdef HAVE_BCG729
 | 
					 | 
				
			||||||
		bcg729DecoderChannelContextStruct *g729_dec;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	} src;
 | 
					 | 
				
			||||||
	size_t src_frame_size;
 | 
					 | 
				
			||||||
	size_t src_samples_per_frame;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* processing */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* encoding */
 | 
					 | 
				
			||||||
	enum audio_format dst_fmt;
 | 
					 | 
				
			||||||
	union {
 | 
					 | 
				
			||||||
		gsm gsm_handle;
 | 
					 | 
				
			||||||
#ifdef HAVE_BCG729
 | 
					 | 
				
			||||||
		bcg729EncoderChannelContextStruct *g729_enc;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	} dst;
 | 
					 | 
				
			||||||
	size_t dst_frame_size;
 | 
					 | 
				
			||||||
	size_t dst_samples_per_frame;
 | 
					 | 
				
			||||||
	int dst_packet_duration;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int is_running;
 | 
					 | 
				
			||||||
	uint16_t next_seq;
 | 
					 | 
				
			||||||
	uint32_t next_time;
 | 
					 | 
				
			||||||
	int16_t samples[10*160];
 | 
					 | 
				
			||||||
	size_t sample_cnt;
 | 
					 | 
				
			||||||
	size_t sample_offs;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int mgcp_transcoding_setup(struct mgcp_endpoint *endp,
 | 
					 | 
				
			||||||
			   struct mgcp_rtp_end *dst_end,
 | 
					 | 
				
			||||||
			   struct mgcp_rtp_end *src_end);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void mgcp_transcoding_net_downlink_format(struct mgcp_endpoint *endp,
 | 
					 | 
				
			||||||
					  int *payload_type,
 | 
					 | 
				
			||||||
					  const char**audio_name,
 | 
					 | 
				
			||||||
					  const char**fmtp_extra);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int mgcp_transcoding_process_rtp(struct mgcp_endpoint *endp,
 | 
					 | 
				
			||||||
				 struct mgcp_rtp_end *dst_end,
 | 
					 | 
				
			||||||
				 char *data, int *len, int buf_size);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int mgcp_transcoding_get_frame_size(void *state_, int nsamples, int dst);
 | 
					 | 
				
			||||||
#endif /* OPENBSC_MGCP_TRANSCODE_H */
 | 
					 | 
				
			||||||
@@ -1,41 +0,0 @@
 | 
				
			|||||||
#ifndef _OPENBSC_OSMUX_H_
 | 
					 | 
				
			||||||
#define _OPENBSC_OSMUX_H_
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <osmocom/netif/osmux.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define OSMUX_PORT	1984
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum {
 | 
					 | 
				
			||||||
	OSMUX_ROLE_BSC = 0,
 | 
					 | 
				
			||||||
	OSMUX_ROLE_BSC_NAT,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int osmux_init(int role, struct mgcp_config *cfg);
 | 
					 | 
				
			||||||
int osmux_enable_endpoint(struct mgcp_endpoint *endp, struct in_addr *addr, uint16_t port);
 | 
					 | 
				
			||||||
void osmux_disable_endpoint(struct mgcp_endpoint *endp);
 | 
					 | 
				
			||||||
void osmux_allocate_cid(struct mgcp_endpoint *endp);
 | 
					 | 
				
			||||||
void osmux_release_cid(struct mgcp_endpoint *endp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int osmux_xfrm_to_rtp(struct mgcp_endpoint *endp, int type, char *buf, int rc);
 | 
					 | 
				
			||||||
int osmux_xfrm_to_osmux(int type, char *buf, int rc, struct mgcp_endpoint *endp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int osmux_send_dummy(struct mgcp_endpoint *endp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int osmux_get_cid(void);
 | 
					 | 
				
			||||||
void osmux_put_cid(uint8_t osmux_cid);
 | 
					 | 
				
			||||||
int osmux_used_cid(void);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum osmux_state {
 | 
					 | 
				
			||||||
	OSMUX_STATE_DISABLED = 0,
 | 
					 | 
				
			||||||
	OSMUX_STATE_NEGOTIATING,
 | 
					 | 
				
			||||||
	OSMUX_STATE_ACTIVATING,
 | 
					 | 
				
			||||||
	OSMUX_STATE_ENABLED,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum osmux_usage {
 | 
					 | 
				
			||||||
	OSMUX_USAGE_OFF = 0,
 | 
					 | 
				
			||||||
	OSMUX_USAGE_ON = 1,
 | 
					 | 
				
			||||||
	OSMUX_USAGE_ONLY = 2,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
@@ -1,31 +0,0 @@
 | 
				
			|||||||
#ifndef OPENBSC_VTY_H
 | 
					 | 
				
			||||||
#define OPENBSC_VTY_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <osmocom/vty/vty.h>
 | 
					 | 
				
			||||||
#include <osmocom/vty/buffer.h>
 | 
					 | 
				
			||||||
#include <osmocom/vty/command.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct gsm_network;
 | 
					 | 
				
			||||||
struct vty;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void openbsc_vty_print_statistics(struct vty *vty, struct gsm_network *);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct buffer *vty_argv_to_buffer(int argc, const char *argv[], int base);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern struct cmd_element cfg_description_cmd;
 | 
					 | 
				
			||||||
extern struct cmd_element cfg_no_description_cmd;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum mgcp_vty_node {
 | 
					 | 
				
			||||||
	MGCP_NODE = _LAST_OSMOVTY_NODE + 1,
 | 
					 | 
				
			||||||
	TRUNK_NODE,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct log_info;
 | 
					 | 
				
			||||||
int bsc_vty_init(struct gsm_network *network);
 | 
					 | 
				
			||||||
int bsc_vty_init_extra(void);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void msc_vty_init(struct gsm_network *msc_network);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct gsm_network *gsmnet_from_vty(struct vty *vty);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
@@ -3,7 +3,14 @@ noinst_HEADERS = \
 | 
				
			|||||||
	mgcp_msg.h \
 | 
						mgcp_msg.h \
 | 
				
			||||||
	mgcp_conn.h \
 | 
						mgcp_conn.h \
 | 
				
			||||||
	mgcp_stat.h \
 | 
						mgcp_stat.h \
 | 
				
			||||||
	mgcp_ep.h \
 | 
						mgcp_endp.h \
 | 
				
			||||||
	mgcp_sdp.h \
 | 
						mgcp_sdp.h \
 | 
				
			||||||
 | 
						mgcp_codec.h \
 | 
				
			||||||
 | 
						mgcp_ctrl.h \
 | 
				
			||||||
 | 
						mgcp_trunk.h \
 | 
				
			||||||
	debug.h \
 | 
						debug.h \
 | 
				
			||||||
 | 
						mgcp_ratectr.h \
 | 
				
			||||||
 | 
						mgcp_e1.h \
 | 
				
			||||||
 | 
						mgcp_network.h \
 | 
				
			||||||
 | 
						mgcp_protocol.h \
 | 
				
			||||||
	$(NULL)
 | 
						$(NULL)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,6 +29,7 @@
 | 
				
			|||||||
/* Debug Areas of the code */
 | 
					/* Debug Areas of the code */
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
	DRTP,
 | 
						DRTP,
 | 
				
			||||||
 | 
						DE1,
 | 
				
			||||||
	Debug_LastEntry,
 | 
						Debug_LastEntry,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,6 +23,7 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <osmocom/core/msgb.h>
 | 
					#include <osmocom/core/msgb.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/socket.h>
 | 
				
			||||||
#include <osmocom/core/write_queue.h>
 | 
					#include <osmocom/core/write_queue.h>
 | 
				
			||||||
#include <osmocom/core/timer.h>
 | 
					#include <osmocom/core/timer.h>
 | 
				
			||||||
#include <osmocom/core/logging.h>
 | 
					#include <osmocom/core/logging.h>
 | 
				
			||||||
@@ -33,6 +34,9 @@
 | 
				
			|||||||
#include <sys/types.h>
 | 
					#include <sys/types.h>
 | 
				
			||||||
#include <sys/socket.h>
 | 
					#include <sys/socket.h>
 | 
				
			||||||
#include <netinet/in.h>
 | 
					#include <netinet/in.h>
 | 
				
			||||||
 | 
					#include <pthread.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "mgcp_ratectr.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define RTP_PORT_DEFAULT_RANGE_START 16002
 | 
					#define RTP_PORT_DEFAULT_RANGE_START 16002
 | 
				
			||||||
#define RTP_PORT_DEFAULT_RANGE_END RTP_PORT_DEFAULT_RANGE_START + 64
 | 
					#define RTP_PORT_DEFAULT_RANGE_END RTP_PORT_DEFAULT_RANGE_START + 64
 | 
				
			||||||
@@ -42,7 +46,7 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
struct mgcp_endpoint;
 | 
					struct mgcp_endpoint;
 | 
				
			||||||
struct mgcp_config;
 | 
					struct mgcp_config;
 | 
				
			||||||
struct mgcp_trunk_config;
 | 
					struct mgcp_trunk;
 | 
				
			||||||
struct mgcp_rtp_end;
 | 
					struct mgcp_rtp_end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MGCP_ENDP_CRCX 1
 | 
					#define MGCP_ENDP_CRCX 1
 | 
				
			||||||
@@ -59,10 +63,7 @@ struct mgcp_rtp_end;
 | 
				
			|||||||
#define MGCP_POLICY_REJECT	5
 | 
					#define MGCP_POLICY_REJECT	5
 | 
				
			||||||
#define MGCP_POLICY_DEFER	6
 | 
					#define MGCP_POLICY_DEFER	6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef int (*mgcp_realloc)(struct mgcp_trunk_config *cfg, int endpoint);
 | 
					typedef int (*mgcp_reset)(struct mgcp_trunk *cfg);
 | 
				
			||||||
typedef int (*mgcp_change)(struct mgcp_trunk_config *cfg, int endpoint, int state);
 | 
					 | 
				
			||||||
typedef int (*mgcp_policy)(struct mgcp_trunk_config *cfg, int endpoint, int state, const char *transactio_id);
 | 
					 | 
				
			||||||
typedef int (*mgcp_reset)(struct mgcp_trunk_config *cfg);
 | 
					 | 
				
			||||||
typedef int (*mgcp_rqnt)(struct mgcp_endpoint *endp, char tone);
 | 
					typedef int (*mgcp_rqnt)(struct mgcp_endpoint *endp, char tone);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@@ -74,14 +75,17 @@ typedef int (*mgcp_rqnt)(struct mgcp_endpoint *endp, char tone);
 | 
				
			|||||||
typedef int (*mgcp_processing)(struct mgcp_endpoint *endp,
 | 
					typedef int (*mgcp_processing)(struct mgcp_endpoint *endp,
 | 
				
			||||||
			       struct mgcp_rtp_end *dst_end,
 | 
								       struct mgcp_rtp_end *dst_end,
 | 
				
			||||||
			       char *data, int *len, int buf_size);
 | 
								       char *data, int *len, int buf_size);
 | 
				
			||||||
typedef int (*mgcp_processing_setup)(struct mgcp_endpoint *endp,
 | 
					 | 
				
			||||||
				     struct mgcp_rtp_end *dst_end,
 | 
					 | 
				
			||||||
				     struct mgcp_rtp_end *src_end);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct mgcp_conn_rtp;
 | 
					struct mgcp_conn_rtp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef int (*mgcp_processing_setup)(struct mgcp_endpoint *endp,
 | 
				
			||||||
 | 
									     struct mgcp_conn_rtp *conn_dst,
 | 
				
			||||||
 | 
									     struct mgcp_conn_rtp *conn_src);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct mgcp_rtp_codec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef void (*mgcp_get_format)(struct mgcp_endpoint *endp,
 | 
					typedef void (*mgcp_get_format)(struct mgcp_endpoint *endp,
 | 
				
			||||||
				int *payload_type,
 | 
									const struct mgcp_rtp_codec **codec,
 | 
				
			||||||
				const char**subtype_name,
 | 
					 | 
				
			||||||
				const char **fmtp_extra,
 | 
									const char **fmtp_extra,
 | 
				
			||||||
				struct mgcp_conn_rtp *conn);
 | 
									struct mgcp_conn_rtp *conn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -89,8 +93,10 @@ typedef void (*mgcp_get_format)(struct mgcp_endpoint *endp,
 | 
				
			|||||||
 * This holds information on how to allocate ports
 | 
					 * This holds information on how to allocate ports
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
struct mgcp_port_range {
 | 
					struct mgcp_port_range {
 | 
				
			||||||
 | 
						pthread_mutex_t lock;
 | 
				
			||||||
	/* addr or NULL to fall-back to default */
 | 
						/* addr or NULL to fall-back to default */
 | 
				
			||||||
	char *bind_addr;
 | 
						char bind_addr_v4[INET6_ADDRSTRLEN];
 | 
				
			||||||
 | 
						char bind_addr_v6[INET6_ADDRSTRLEN];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* dynamically allocated */
 | 
						/* dynamically allocated */
 | 
				
			||||||
	int range_start;
 | 
						int range_start;
 | 
				
			||||||
@@ -105,55 +111,17 @@ struct mgcp_port_range {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* There are up to three modes in which the keep-alive dummy packet can be
 | 
					/* There are up to three modes in which the keep-alive dummy packet can be
 | 
				
			||||||
 * sent. The beviour is controlled viw the keepalive_interval member of the
 | 
					 * sent. The behaviour is controlled via the keepalive_interval member of the
 | 
				
			||||||
 * trunk config. If that member is set to 0 (MGCP_KEEPALIVE_NEVER) no dummy-
 | 
					 * trunk config. If that member is set to 0 (MGCP_KEEPALIVE_NEVER) no dummy-
 | 
				
			||||||
 * packet is sent at all and the timer that sends regular dummy packets
 | 
					 * packet is sent at all and the timer that sends regular dummy packets
 | 
				
			||||||
 * is no longer scheduled. If the keepalive_interval is set to -1, only
 | 
					 * is no longer scheduled. If the keepalive_interval is set to -1, only
 | 
				
			||||||
 * one dummy packet is sent when an CRCX or an MDCX is performed. No timer
 | 
					 * one dummy packet is sent when an CRCX or an MDCX is performed. No timer
 | 
				
			||||||
 * is scheduled. For all vales greater 0, the a timer is scheduled and the
 | 
					 * is scheduled. For all vales greater 0, the timer is scheduled and the
 | 
				
			||||||
 * value is used as interval. See also mgcp_keepalive_timer_cb(),
 | 
					 * value is used as interval. See also mgcp_keepalive_timer_cb(),
 | 
				
			||||||
 * handle_modify_con(), and handle_create_con() */
 | 
					 * handle_modify_con(), and handle_create_con() */
 | 
				
			||||||
#define MGCP_KEEPALIVE_ONCE (-1)
 | 
					#define MGCP_KEEPALIVE_ONCE (-1)
 | 
				
			||||||
#define MGCP_KEEPALIVE_NEVER 0
 | 
					#define MGCP_KEEPALIVE_NEVER 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct mgcp_trunk_config {
 | 
					 | 
				
			||||||
	struct llist_head entry;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct mgcp_config *cfg;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int trunk_nr;
 | 
					 | 
				
			||||||
	int trunk_type;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	char *audio_fmtp_extra;
 | 
					 | 
				
			||||||
	char *audio_name;
 | 
					 | 
				
			||||||
	int audio_payload;
 | 
					 | 
				
			||||||
	int audio_send_ptime;
 | 
					 | 
				
			||||||
	int audio_send_name;
 | 
					 | 
				
			||||||
	int audio_loop;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int no_audio_transcoding;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int omit_rtcp;
 | 
					 | 
				
			||||||
	int keepalive_interval;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* RTP patching */
 | 
					 | 
				
			||||||
	int force_constant_ssrc; /* 0: don't, 1: once */
 | 
					 | 
				
			||||||
	int force_aligned_timing;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* spec handling */
 | 
					 | 
				
			||||||
	int force_realloc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* timer */
 | 
					 | 
				
			||||||
	struct osmo_timer_list keepalive_timer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* When set, incoming RTP packets are not filtered
 | 
					 | 
				
			||||||
	 * when ports and ip-address do not match (debug) */
 | 
					 | 
				
			||||||
	int rtp_accept_all;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	unsigned int number_endpoints;
 | 
					 | 
				
			||||||
	struct mgcp_endpoint *endpoints;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum mgcp_role {
 | 
					enum mgcp_role {
 | 
				
			||||||
	MGCP_BSC = 0,
 | 
						MGCP_BSC = 0,
 | 
				
			||||||
	MGCP_BSC_NAT,
 | 
						MGCP_BSC_NAT,
 | 
				
			||||||
@@ -161,9 +129,9 @@ enum mgcp_role {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
struct mgcp_config {
 | 
					struct mgcp_config {
 | 
				
			||||||
	int source_port;
 | 
						int source_port;
 | 
				
			||||||
	char *local_ip;
 | 
						char local_ip[INET6_ADDRSTRLEN];
 | 
				
			||||||
	char *source_addr;
 | 
						char source_addr[INET6_ADDRSTRLEN];
 | 
				
			||||||
	char *call_agent_addr;
 | 
						char call_agent_addr[INET6_ADDRSTRLEN];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* RTP processing */
 | 
						/* RTP processing */
 | 
				
			||||||
	mgcp_processing rtp_processing_cb;
 | 
						mgcp_processing rtp_processing_cb;
 | 
				
			||||||
@@ -175,20 +143,15 @@ struct mgcp_config {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	struct mgcp_port_range net_ports;
 | 
						struct mgcp_port_range net_ports;
 | 
				
			||||||
	int endp_dscp;
 | 
						int endp_dscp;
 | 
				
			||||||
 | 
						int endp_priority;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int force_ptime;
 | 
						int force_ptime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mgcp_change change_cb;
 | 
					 | 
				
			||||||
	mgcp_policy policy_cb;
 | 
					 | 
				
			||||||
	mgcp_reset reset_cb;
 | 
						mgcp_reset reset_cb;
 | 
				
			||||||
	mgcp_realloc realloc_cb;
 | 
					 | 
				
			||||||
	mgcp_rqnt rqnt_cb;
 | 
						mgcp_rqnt rqnt_cb;
 | 
				
			||||||
	void *data;
 | 
						void *data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uint32_t last_call_id;
 | 
						/* list holding the trunks */
 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* trunk handling */
 | 
					 | 
				
			||||||
	struct mgcp_trunk_config trunk;
 | 
					 | 
				
			||||||
	struct llist_head trunks;
 | 
						struct llist_head trunks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	enum mgcp_role role;
 | 
						enum mgcp_role role;
 | 
				
			||||||
@@ -196,7 +159,7 @@ struct mgcp_config {
 | 
				
			|||||||
	/* osmux translator: 0 means disabled, 1 means enabled */
 | 
						/* osmux translator: 0 means disabled, 1 means enabled */
 | 
				
			||||||
	int osmux;
 | 
						int osmux;
 | 
				
			||||||
	/* addr to bind the server to */
 | 
						/* addr to bind the server to */
 | 
				
			||||||
	char *osmux_addr;
 | 
						char osmux_addr[INET6_ADDRSTRLEN];
 | 
				
			||||||
	/* The BSC-NAT may ask for enabling osmux on demand. This tells us if
 | 
						/* The BSC-NAT may ask for enabling osmux on demand. This tells us if
 | 
				
			||||||
	 * the osmux socket is already initialized.
 | 
						 * the osmux socket is already initialized.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
@@ -211,6 +174,18 @@ struct mgcp_config {
 | 
				
			|||||||
	 * message.
 | 
						 * message.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	uint16_t osmux_dummy;
 | 
						uint16_t osmux_dummy;
 | 
				
			||||||
 | 
						/* domain name of the media gateway */
 | 
				
			||||||
 | 
						char domain[255+1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* time after which inactive connections (CIs) get closed */
 | 
				
			||||||
 | 
						int conn_timeout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* osmocom CTRL interface */
 | 
				
			||||||
 | 
						struct ctrl_handle *ctrl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* global rate counters to measure the MGWs overall performance and
 | 
				
			||||||
 | 
						 * health */
 | 
				
			||||||
 | 
						struct mgcp_ratectr_global ratectr;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* config management */
 | 
					/* config management */
 | 
				
			||||||
@@ -218,9 +193,7 @@ struct mgcp_config *mgcp_config_alloc(void);
 | 
				
			|||||||
int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg,
 | 
					int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg,
 | 
				
			||||||
		      enum mgcp_role role);
 | 
							      enum mgcp_role role);
 | 
				
			||||||
int mgcp_vty_init(void);
 | 
					int mgcp_vty_init(void);
 | 
				
			||||||
int mgcp_endpoints_allocate(struct mgcp_trunk_config *cfg);
 | 
					void mgcp_trunk_set_keepalive(struct mgcp_trunk *trunk, int interval);
 | 
				
			||||||
void mgcp_release_endp(struct mgcp_endpoint *endp);
 | 
					 | 
				
			||||||
void mgcp_trunk_set_keepalive(struct mgcp_trunk_config *tcfg, int interval);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * format helper functions
 | 
					 * format helper functions
 | 
				
			||||||
@@ -228,9 +201,10 @@ void mgcp_trunk_set_keepalive(struct mgcp_trunk_config *tcfg, int interval);
 | 
				
			|||||||
struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg);
 | 
					struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int mgcp_send_reset_ep(struct mgcp_endpoint *endp, int endpoint);
 | 
					int mgcp_send_reset_ep(struct mgcp_endpoint *endp);
 | 
				
			||||||
int mgcp_send_reset_all(struct mgcp_config *cfg);
 | 
					int mgcp_send_reset_all(struct mgcp_config *cfg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int mgcp_create_bind(const char *source_addr, struct osmo_fd *fd, int port);
 | 
					int mgcp_create_bind(const char *source_addr, struct osmo_fd *fd, int port, uint8_t dscp,
 | 
				
			||||||
int mgcp_udp_send(int fd, struct in_addr *addr, int port, char *buf, int len);
 | 
							     uint8_t prio);
 | 
				
			||||||
 | 
					int mgcp_udp_send(int fd, struct osmo_sockaddr *addr, int port, const char *buf, int len);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										19
									
								
								include/osmocom/mgcp/mgcp_codec.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								include/osmocom/mgcp/mgcp_codec.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DEFAULT_RTP_AUDIO_FRAME_DUR_NUM 20
 | 
				
			||||||
 | 
					#define DEFAULT_RTP_AUDIO_FRAME_DUR_DEN 1000
 | 
				
			||||||
 | 
					#define DEFAULT_RTP_AUDIO_PACKET_DURATION_MS 20
 | 
				
			||||||
 | 
					#define DEFAULT_RTP_AUDIO_DEFAULT_RATE  8000
 | 
				
			||||||
 | 
					#define DEFAULT_RTP_AUDIO_DEFAULT_CHANNELS 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PTYPE_UNDEFINED (-1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct mgcp_conn_rtp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void mgcp_codec_summary(struct mgcp_conn_rtp *conn);
 | 
				
			||||||
 | 
					void mgcp_codec_reset_all(struct mgcp_conn_rtp *conn);
 | 
				
			||||||
 | 
					int mgcp_codec_add(struct mgcp_conn_rtp *conn, int payload_type, const char *audio_name, const struct mgcp_codec_param *param);
 | 
				
			||||||
 | 
					int mgcp_codec_decide(struct mgcp_conn_rtp *conn);
 | 
				
			||||||
 | 
					int mgcp_codec_pt_translate(struct mgcp_conn_rtp *conn_src, struct mgcp_conn_rtp *conn_dst, int payload_type);
 | 
				
			||||||
 | 
					const struct mgcp_rtp_codec *mgcp_codec_pt_find_by_subtype_name(struct mgcp_conn_rtp *conn,
 | 
				
			||||||
 | 
													const char *subtype_name, unsigned int match_nr);
 | 
				
			||||||
@@ -49,6 +49,21 @@ enum mgcp_connection_mode {
 | 
				
			|||||||
	MGCP_CONN_LOOPBACK  = 4 | MGCP_CONN_RECV_SEND,
 | 
						MGCP_CONN_LOOPBACK  = 4 | MGCP_CONN_RECV_SEND,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MGCP_X_OSMO_IGN_HEADER "X-Osmo-IGN:"
 | 
				
			||||||
 | 
					#define MGCP_X_OSMO_OSMUX_HEADER "X-Osmux:"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Values should be bitwise-OR-able */
 | 
				
			||||||
 | 
					enum mgcp_x_osmo_ign {
 | 
				
			||||||
 | 
						MGCP_X_OSMO_IGN_NONE = 0,
 | 
				
			||||||
 | 
						MGCP_X_OSMO_IGN_CALLID = 1,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Codec parameters (communicated via SDP/fmtp) */
 | 
				
			||||||
 | 
					struct mgcp_codec_param {
 | 
				
			||||||
 | 
						bool amr_octet_aligned_present;
 | 
				
			||||||
 | 
						bool amr_octet_aligned;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Ensure that the msg->l2h is NUL terminated. */
 | 
					/* Ensure that the msg->l2h is NUL terminated. */
 | 
				
			||||||
static inline int mgcp_msg_terminate_nul(struct msgb *msg)
 | 
					static inline int mgcp_msg_terminate_nul(struct msgb *msg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -68,4 +83,29 @@ static inline int mgcp_msg_terminate_nul(struct msgb *msg)
 | 
				
			|||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Maximum length of the comment field */
 | 
				
			||||||
 | 
					#define MGCP_COMMENT_MAXLEN 256
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Maximum allowed String length of Connection Identifiers as per spec
 | 
				
			||||||
 | 
					 * (see also RFC3435 2.1.3.2 Names of Connections), plus one for '\0'. */
 | 
				
			||||||
 | 
					#define MGCP_CONN_ID_MAXLEN 32+1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Deprecated: old name of MGCP_CONN_ID_MAXLEN. */
 | 
				
			||||||
 | 
					#define MGCP_CONN_ID_LENGTH MGCP_CONN_ID_MAXLEN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* String length of Endpoint Identifiers.
 | 
				
			||||||
 | 
					/  (see also RFC3435 section 3.2.1.3) */
 | 
				
			||||||
 | 
					#define MGCP_ENDPOINT_MAXLEN (255*2+1+1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* A prefix to denote the virtual trunk (RTP on both ends) */
 | 
				
			||||||
 | 
					#define MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK "rtpbridge/"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* A prefix to denote the e1 trunk
 | 
				
			||||||
 | 
					 * (see also RFC3435 section E.2) */
 | 
				
			||||||
 | 
					#define MGCP_ENDPOINT_PREFIX_E1_TRUNK "ds/e1-"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Maximal number of payload types / codecs that can be negotiated via SDP at
 | 
				
			||||||
 | 
					 * at once. */
 | 
				
			||||||
 | 
					#define MGCP_MAX_CODECS 10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,18 +23,168 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <osmocom/mgcp/mgcp_internal.h>
 | 
					#include <osmocom/mgcp/mgcp.h>
 | 
				
			||||||
 | 
					#include <osmocom/mgcp/mgcp_network.h>
 | 
				
			||||||
 | 
					#include <osmocom/mgcp/osmux.h>
 | 
				
			||||||
#include <osmocom/core/linuxlist.h>
 | 
					#include <osmocom/core/linuxlist.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/rate_ctr.h>
 | 
				
			||||||
#include <inttypes.h>
 | 
					#include <inttypes.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LOGPCONN(conn, cat, level, fmt, args...) \
 | 
				
			||||||
 | 
					LOGPENDP((conn)->endp, cat, level, "CI:%s " fmt, \
 | 
				
			||||||
 | 
					         (conn)->id, \
 | 
				
			||||||
 | 
					         ## args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LOG_CONN(conn, level, fmt, args...) \
 | 
				
			||||||
 | 
						LOGP(DRTP, level, "(%s I:%s) " fmt, \
 | 
				
			||||||
 | 
						     (conn)->endp ? (conn)->endp->name : "none", (conn)->id, ## args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LOG_CONN_RTP(conn_rtp, level, fmt, args...) \
 | 
				
			||||||
 | 
						LOG_CONN((conn_rtp)->conn, level, fmt, ## args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Specific rtp connection type (see struct mgcp_conn_rtp) */
 | 
				
			||||||
 | 
					enum mgcp_conn_rtp_type {
 | 
				
			||||||
 | 
						MGCP_RTP_DEFAULT	= 0,
 | 
				
			||||||
 | 
						MGCP_OSMUX_BSC,
 | 
				
			||||||
 | 
						MGCP_OSMUX_BSC_NAT,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! Connection type, specifies which member of the union "u" in mgcp_conn
 | 
				
			||||||
 | 
					 *  contains a useful connection description (currently only RTP) */
 | 
				
			||||||
 | 
					enum mgcp_conn_type {
 | 
				
			||||||
 | 
						MGCP_CONN_TYPE_RTP,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* MGCP connection (RTP) */
 | 
				
			||||||
 | 
					struct mgcp_conn_rtp {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Backpointer to conn struct */
 | 
				
			||||||
 | 
						struct mgcp_conn *conn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Specific connection type */
 | 
				
			||||||
 | 
						enum mgcp_conn_rtp_type type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Port status */
 | 
				
			||||||
 | 
						struct mgcp_rtp_end end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Sequence bits */
 | 
				
			||||||
 | 
						struct mgcp_rtp_state state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* taps for the rtp connection; one per direction */
 | 
				
			||||||
 | 
						struct mgcp_rtp_tap tap_in;
 | 
				
			||||||
 | 
						struct mgcp_rtp_tap tap_out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Osmux states (optional) */
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							/* Osmux state: disabled, activating, active */
 | 
				
			||||||
 | 
							enum osmux_state state;
 | 
				
			||||||
 | 
							/* Is cid holding valid data? is it allocated from pool? */
 | 
				
			||||||
 | 
							bool cid_allocated;
 | 
				
			||||||
 | 
							/* Allocated Osmux circuit ID for this conn */
 | 
				
			||||||
 | 
							uint8_t cid;
 | 
				
			||||||
 | 
							/* handle to batch messages */
 | 
				
			||||||
 | 
							struct osmux_in_handle *in;
 | 
				
			||||||
 | 
							/* handle to unbatch messages */
 | 
				
			||||||
 | 
							struct osmux_out_handle out;
 | 
				
			||||||
 | 
							/* statistics */
 | 
				
			||||||
 | 
							struct {
 | 
				
			||||||
 | 
								uint32_t chunks;
 | 
				
			||||||
 | 
								uint32_t octets;
 | 
				
			||||||
 | 
							} stats;
 | 
				
			||||||
 | 
						} osmux;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct rate_ctr_group *rate_ctr_group;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! MGCP connection (untyped) */
 | 
				
			||||||
 | 
					struct mgcp_conn {
 | 
				
			||||||
 | 
						/*! list head */
 | 
				
			||||||
 | 
						struct llist_head entry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! Backpointer to the endpoint where the conn belongs to */
 | 
				
			||||||
 | 
						struct mgcp_endpoint *endp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! type of the connection (union) */
 | 
				
			||||||
 | 
						enum mgcp_conn_type type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! mode of the connection */
 | 
				
			||||||
 | 
						enum mgcp_connection_mode mode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! copy of the mode to restore the original setting (VTY) */
 | 
				
			||||||
 | 
						enum mgcp_connection_mode mode_orig;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! connection id to identify the connection */
 | 
				
			||||||
 | 
						char id[MGCP_CONN_ID_MAXLEN];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! human readable name (vty, logging) */
 | 
				
			||||||
 | 
						char name[256];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! activity tracker (for cleaning up inactive connections) */
 | 
				
			||||||
 | 
						struct osmo_timer_list watchdog;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! union with connection description */
 | 
				
			||||||
 | 
						union {
 | 
				
			||||||
 | 
							struct mgcp_conn_rtp rtp;
 | 
				
			||||||
 | 
						} u;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! pointer to optional private data */
 | 
				
			||||||
 | 
						void *priv;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* RTP connection related counters */
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						IN_STREAM_ERR_TSTMP_CTR,
 | 
				
			||||||
 | 
						OUT_STREAM_ERR_TSTMP_CTR,
 | 
				
			||||||
 | 
					        RTP_PACKETS_RX_CTR,
 | 
				
			||||||
 | 
					        RTP_OCTETS_RX_CTR,
 | 
				
			||||||
 | 
					        RTP_PACKETS_TX_CTR,
 | 
				
			||||||
 | 
					        RTP_OCTETS_TX_CTR,
 | 
				
			||||||
 | 
					        RTP_DROPPED_PACKETS_CTR,
 | 
				
			||||||
 | 
					        RTP_NUM_CONNECTIONS,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* RTP per-connection statistics. Instances of the corresponding rate counter group
 | 
				
			||||||
 | 
					 * exist for the lifetime of an RTP connection.
 | 
				
			||||||
 | 
					 * Must be kept in sync with all_rtp_conn_rate_ctr_desc below */
 | 
				
			||||||
 | 
					static const struct rate_ctr_desc mgcp_conn_rate_ctr_desc[] = {
 | 
				
			||||||
 | 
						[IN_STREAM_ERR_TSTMP_CTR] = {"stream_err_tstmp:in", "Inbound rtp-stream timestamp errors."},
 | 
				
			||||||
 | 
						[OUT_STREAM_ERR_TSTMP_CTR] = {"stream_err_tstmp:out", "Outbound rtp-stream timestamp errors."},
 | 
				
			||||||
 | 
						[RTP_PACKETS_RX_CTR] = {"rtp:packets_rx", "Inbound rtp packets."},
 | 
				
			||||||
 | 
						[RTP_OCTETS_RX_CTR] = {"rtp:octets_rx", "Inbound rtp octets."},
 | 
				
			||||||
 | 
						[RTP_PACKETS_TX_CTR] = {"rtp:packets_tx", "Outbound rtp packets."},
 | 
				
			||||||
 | 
						[RTP_OCTETS_TX_CTR] = {"rtp:octets_tx", "Outbound rtp octets."},
 | 
				
			||||||
 | 
						[RTP_DROPPED_PACKETS_CTR] = {"rtp:dropped", "dropped rtp packets."}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Aggregated RTP connection stats. These are updated when an RTP connection is freed.
 | 
				
			||||||
 | 
					 * Must be kept in sync with mgcp_conn_rate_ctr_desc above */
 | 
				
			||||||
 | 
					static const struct rate_ctr_desc all_rtp_conn_rate_ctr_desc[] = {
 | 
				
			||||||
 | 
						[IN_STREAM_ERR_TSTMP_CTR] = {"all_rtp:err_tstmp_in", "Total inbound rtp-stream timestamp errors."},
 | 
				
			||||||
 | 
						[OUT_STREAM_ERR_TSTMP_CTR] = {"all_rtp:err_tstmp_out", "Total outbound rtp-stream timestamp errors."},
 | 
				
			||||||
 | 
						[RTP_PACKETS_RX_CTR] = {"all_rtp:packets_rx", "Total inbound rtp packets."},
 | 
				
			||||||
 | 
						[RTP_OCTETS_RX_CTR] = {"all_rtp:octets_rx", "Total inbound rtp octets."},
 | 
				
			||||||
 | 
						[RTP_PACKETS_TX_CTR] = {"all_rtp:packets_tx", "Total outbound rtp packets."},
 | 
				
			||||||
 | 
						[RTP_OCTETS_TX_CTR] = {"all_rtp:octets_tx", "Total outbound rtp octets."},
 | 
				
			||||||
 | 
						[RTP_DROPPED_PACKETS_CTR] = {"all_rtp:dropped", "Total dropped rtp packets."},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* This last counter does not exist in per-connection stats, only here. */
 | 
				
			||||||
 | 
						[RTP_NUM_CONNECTIONS] = {"all_rtp:num_closed_conns", "Total number of rtp connections closed."}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Was conn configured to handle Osmux? */
 | 
				
			||||||
 | 
					static inline bool mgcp_conn_rtp_is_osmux(const struct mgcp_conn_rtp *conn) {
 | 
				
			||||||
 | 
						return conn->type == MGCP_OSMUX_BSC || conn->type == MGCP_OSMUX_BSC_NAT;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct mgcp_conn *mgcp_conn_alloc(void *ctx, struct mgcp_endpoint *endp,
 | 
					struct mgcp_conn *mgcp_conn_alloc(void *ctx, struct mgcp_endpoint *endp,
 | 
				
			||||||
				  uint32_t id, enum mgcp_conn_type type,
 | 
									  enum mgcp_conn_type type, char *name);
 | 
				
			||||||
				  char *name);
 | 
					struct mgcp_conn *mgcp_conn_get(struct mgcp_endpoint *endp, const char *id);
 | 
				
			||||||
struct mgcp_conn *mgcp_conn_get(struct mgcp_endpoint *endp, uint32_t id);
 | 
					 | 
				
			||||||
struct mgcp_conn_rtp *mgcp_conn_get_rtp(struct mgcp_endpoint *endp,
 | 
					struct mgcp_conn_rtp *mgcp_conn_get_rtp(struct mgcp_endpoint *endp,
 | 
				
			||||||
					uint32_t id);
 | 
										const char *id);
 | 
				
			||||||
void mgcp_conn_free(struct mgcp_endpoint *endp, uint32_t id);
 | 
					void mgcp_conn_free(struct mgcp_endpoint *endp, const char *id);
 | 
				
			||||||
void mgcp_conn_free_oldest(struct mgcp_endpoint *endp);
 | 
					void mgcp_conn_free_oldest(struct mgcp_endpoint *endp);
 | 
				
			||||||
void mgcp_conn_free_all(struct mgcp_endpoint *endp);
 | 
					void mgcp_conn_free_all(struct mgcp_endpoint *endp);
 | 
				
			||||||
char *mgcp_conn_dump(struct mgcp_conn *conn);
 | 
					char *mgcp_conn_dump(struct mgcp_conn *conn);
 | 
				
			||||||
struct mgcp_conn *mgcp_find_dst_conn(struct mgcp_conn *conn);
 | 
					struct mgcp_conn *mgcp_find_dst_conn(struct mgcp_conn *conn);
 | 
				
			||||||
 | 
					struct mgcp_conn *mgcp_conn_get_oldest(struct mgcp_endpoint *endp);
 | 
				
			||||||
 | 
					void mgcp_conn_watchdog_kick(struct mgcp_conn *conn);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,7 @@
 | 
				
			|||||||
/* Endpoint types */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
					 * (C) 2020 by Harald Welte <laforge@gnumonks.org>
 | 
				
			||||||
 * All Rights Reserved
 | 
					 * All Rights Reserved
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Author: Philipp Maier
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is free software; you can redistribute it and/or modify
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 * it under the terms of the GNU Affero General Public License as published by
 | 
					 * it under the terms of the GNU Affero General Public License as published by
 | 
				
			||||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
					 * the Free Software Foundation; either version 3 of the License, or
 | 
				
			||||||
@@ -21,12 +17,8 @@
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <osmocom/mgcp/mgcp_ep.h>
 | 
					#pragma once
 | 
				
			||||||
#include <osmocom/mgcp/mgcp_internal.h>
 | 
					
 | 
				
			||||||
 | 
					struct ctrl_handle *mgw_ctrl_interface_setup(struct mgcp_config *cfg,
 | 
				
			||||||
 | 
					                                             const char *bind_addr, uint16_t port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Endpoint typeset definition */
 | 
					 | 
				
			||||||
const struct mgcp_endpoint_typeset ep_typeset = {
 | 
					 | 
				
			||||||
	/* Specify endpoint properties for RTP endpoint */
 | 
					 | 
				
			||||||
	.rtp.max_conns = 2,
 | 
					 | 
				
			||||||
	.rtp.dispatch_rtp_cb = mgcp_dispatch_rtp_bridge_cb
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
							
								
								
									
										27
									
								
								include/osmocom/mgcp/mgcp_e1.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								include/osmocom/mgcp/mgcp_e1.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* A 64k timeslot on an E1 line can be subdevied into the following
 | 
				
			||||||
 | 
					 * subslot combinations:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * subslot:                                          offset:
 | 
				
			||||||
 | 
					 * [          ][          ][   16k    ][8k_subslot]  0
 | 
				
			||||||
 | 
					 * [          ][   32k    ][_subslot__][8k_subslot]  1
 | 
				
			||||||
 | 
					 * [          ][ subslot  ][   16k    ][8k_subslot]  2
 | 
				
			||||||
 | 
					 * [   64k    ][__________][_subslot__][8k_subslot]  3
 | 
				
			||||||
 | 
					 * [ timeslot ][          ][   16k    ][8k_subslot]  4
 | 
				
			||||||
 | 
					 * [          ][   32K    ][_subslot__][8k_subslot]  5
 | 
				
			||||||
 | 
					 * [          ][ subslot  ][   16k    ][8k_subslot]  6
 | 
				
			||||||
 | 
					 * [          ][          ][ subslot  ][8k_subslot]  7
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Since overlapping assignment of subslots is not possible there is a limited
 | 
				
			||||||
 | 
					 * set of subslot assignments possible. The e1_rates array lists the possible
 | 
				
			||||||
 | 
					 * assignments as depicted above. Also each subslot assignment comes along with
 | 
				
			||||||
 | 
					 * a bit offset in the E1 bitstream. The e1_offsets arrays lists the bit
 | 
				
			||||||
 | 
					 * offsets. */
 | 
				
			||||||
 | 
					static const uint8_t e1_rates[] = { 64, 32, 32, 16, 16, 16, 16, 8, 8, 8, 8, 8, 8, 8, 8 };
 | 
				
			||||||
 | 
					static const uint8_t e1_offsets[] = { 0, 0, 4, 0, 2, 4, 6, 0, 1, 2, 3, 4, 5, 6, 7 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int mgcp_e1_endp_equip(struct mgcp_endpoint *endp, uint8_t ts, uint8_t ss, uint8_t offs);
 | 
				
			||||||
 | 
					void mgcp_e1_endp_update(struct mgcp_endpoint *endp);
 | 
				
			||||||
 | 
					void mgcp_e1_endp_release(struct mgcp_endpoint *endp);
 | 
				
			||||||
 | 
					int mgcp_e1_send_rtp(struct mgcp_endpoint *endp, struct mgcp_rtp_codec *codec, struct msgb *msg);
 | 
				
			||||||
							
								
								
									
										142
									
								
								include/osmocom/mgcp/mgcp_endp.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								include/osmocom/mgcp/mgcp_endp.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,142 @@
 | 
				
			|||||||
 | 
					/* Endpoint types */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Author: Philipp Maier
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU Affero General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU Affero General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU Affero General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/core/msgb.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/i460_mux.h>
 | 
				
			||||||
 | 
					#include <osmocom/mgcp/mgcp_protocol.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct sockaddr;
 | 
				
			||||||
 | 
					struct mgcp_conn;
 | 
				
			||||||
 | 
					struct mgcp_conn_rtp;
 | 
				
			||||||
 | 
					struct mgcp_endpoint;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Number of E1 subslots (different variants, not all useable at the same time) */
 | 
				
			||||||
 | 
					#define MGCP_ENDP_E1_SUBSLOTS 15
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LOGPENDP(endp, cat, level, fmt, args...) \
 | 
				
			||||||
 | 
					LOGP(cat, level, "endpoint:%s " fmt, \
 | 
				
			||||||
 | 
					     endp ? endp->name : "none", \
 | 
				
			||||||
 | 
					     ## args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_rtp_msg_ctx {
 | 
				
			||||||
 | 
						int proto;
 | 
				
			||||||
 | 
						struct mgcp_conn_rtp *conn_src;
 | 
				
			||||||
 | 
						struct osmo_sockaddr *from_addr;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define OSMO_RTP_MSG_CTX(MSGB) ((struct osmo_rtp_msg_ctx*)(MSGB)->cb)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo_static_assert(sizeof(((struct msgb*)0)->cb) >= sizeof(struct osmo_rtp_msg_ctx), osmo_rtp_msg_ctx_fits_in_msgb_cb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Callback type for RTP dispatcher functions (e.g mgcp_dispatch_rtp_bridge_cb, see below).
 | 
				
			||||||
 | 
					 * The OSMO_RTP_MSG_CTX() should be set appropriately on the msg. */
 | 
				
			||||||
 | 
					typedef int (*mgcp_dispatch_rtp_cb) (struct msgb *msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Callback type for endpoint specific cleanup actions. This function
 | 
				
			||||||
 | 
					 * is automatically executed when a connection is freed (see mgcp_conn_free()
 | 
				
			||||||
 | 
					 * in mgcp_conn.c). Depending on the type of the endpoint there may be endpoint
 | 
				
			||||||
 | 
					 * specific things to take care of once a connection has been removed. */
 | 
				
			||||||
 | 
					typedef void (*mgcp_cleanup_cp) (struct mgcp_endpoint *endp,
 | 
				
			||||||
 | 
									 struct mgcp_conn *conn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! MGCP endpoint properties */
 | 
				
			||||||
 | 
					struct mgcp_endpoint_type {
 | 
				
			||||||
 | 
						/*! maximum number of connections */
 | 
				
			||||||
 | 
						int max_conns;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! callback that defines how to dispatch incoming RTP data */
 | 
				
			||||||
 | 
						mgcp_dispatch_rtp_cb dispatch_rtp_cb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! callback that implements endpoint specific cleanup actions */
 | 
				
			||||||
 | 
						mgcp_cleanup_cp cleanup_cb;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! MGCP endpoint typeset */
 | 
				
			||||||
 | 
					struct mgcp_endpoint_typeset {
 | 
				
			||||||
 | 
						struct mgcp_endpoint_type rtp;
 | 
				
			||||||
 | 
						struct mgcp_endpoint_type e1;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! static MGCP endpoint typeset (pre-initalized, read-only) */
 | 
				
			||||||
 | 
					extern const struct mgcp_endpoint_typeset ep_typeset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! MGCP endpoint model */
 | 
				
			||||||
 | 
					struct mgcp_endpoint {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! Unique endpoint name, used for addressing via MGCP */
 | 
				
			||||||
 | 
						char *name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! Call identifier string (as supplied by the call agant) */
 | 
				
			||||||
 | 
						char *callid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! Local connection options (see mgcp_internal.h) */
 | 
				
			||||||
 | 
						struct mgcp_lco local_options;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! List of struct mgcp_conn, of the connections active on this endpoint */
 | 
				
			||||||
 | 
						struct llist_head conns;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! Backpointer to the trunk this endpoint belongs to */
 | 
				
			||||||
 | 
						struct mgcp_trunk *trunk;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! Endpoint properties (see above) */
 | 
				
			||||||
 | 
						const struct mgcp_endpoint_type *type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! Last MGCP transmission (in case re-transmission is required) */
 | 
				
			||||||
 | 
						char *last_trans;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! Last MGCP response (in case re-transmission is required) */
 | 
				
			||||||
 | 
						char *last_response;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! MGCP_X_OSMO_IGN_* flags from 'X-Osmo-IGN:' header */
 | 
				
			||||||
 | 
						uint32_t x_osmo_ign;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* E1 specific */
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							struct osmo_i460_schan_desc scd;
 | 
				
			||||||
 | 
							struct osmo_i460_subchan *schan;
 | 
				
			||||||
 | 
							struct osmo_fsm_inst *trau_sync_fi;
 | 
				
			||||||
 | 
							struct osmo_trau2rtp_state *trau_rtp_st;
 | 
				
			||||||
 | 
							uint8_t last_amr_ft;
 | 
				
			||||||
 | 
							struct mgcp_rtp_codec *last_codec;
 | 
				
			||||||
 | 
						} e1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct mgcp_endpoint *mgcp_endp_alloc(struct mgcp_trunk *trunk, unsigned int index);
 | 
				
			||||||
 | 
					void mgcp_endp_release(struct mgcp_endpoint *endp);
 | 
				
			||||||
 | 
					int mgcp_endp_claim(struct mgcp_endpoint *endp, const char *callid);
 | 
				
			||||||
 | 
					void mgcp_endp_update(struct mgcp_endpoint *endp);
 | 
				
			||||||
 | 
					bool mgcp_endp_is_wildcarded(const char *epname);
 | 
				
			||||||
 | 
					struct mgcp_endpoint *mgcp_endp_by_name_trunk(int *cause, const char *epname,
 | 
				
			||||||
 | 
										      const struct mgcp_trunk *trunk);
 | 
				
			||||||
 | 
					struct mgcp_endpoint *mgcp_endp_by_name(int *cause, const char *epname,
 | 
				
			||||||
 | 
										struct mgcp_config *cfg);
 | 
				
			||||||
 | 
					bool mgcp_endp_avail(struct mgcp_endpoint *endp);
 | 
				
			||||||
 | 
					void mgcp_endp_add_conn(struct mgcp_endpoint *endp, struct mgcp_conn *conn);
 | 
				
			||||||
 | 
					void mgcp_endp_remove_conn(struct mgcp_endpoint *endp, struct mgcp_conn *conn);
 | 
				
			||||||
 | 
					void mgcp_endp_strip_name(char *epname_stripped, const char *epname,
 | 
				
			||||||
 | 
								 const struct mgcp_trunk *trunk);
 | 
				
			||||||
 | 
					struct mgcp_endpoint *mgcp_endp_find_specific(const char *epname,
 | 
				
			||||||
 | 
								const struct mgcp_trunk *trunk);
 | 
				
			||||||
@@ -1,50 +0,0 @@
 | 
				
			|||||||
/* Endpoint types */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
					 | 
				
			||||||
 * All Rights Reserved
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Author: Philipp Maier
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is free software; you can redistribute it and/or modify
 | 
					 | 
				
			||||||
 * it under the terms of the GNU Affero General Public License as published by
 | 
					 | 
				
			||||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
					 | 
				
			||||||
 * (at your option) any later version.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is distributed in the hope that it will be useful,
 | 
					 | 
				
			||||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 | 
				
			||||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					 | 
				
			||||||
 * GNU Affero General Public License for more details.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * You should have received a copy of the GNU Affero General Public License
 | 
					 | 
				
			||||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#pragma once
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct sockaddr_in;
 | 
					 | 
				
			||||||
struct mgcp_conn;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Callback type for RTP dispatcher functions
 | 
					 | 
				
			||||||
   (e.g mgcp_dispatch_rtp_bridge_cb, see below) */
 | 
					 | 
				
			||||||
typedef int (*mgcp_dispatch_rtp_cb) (int proto, struct sockaddr_in * addr,
 | 
					 | 
				
			||||||
				     char *buf, unsigned int buf_size,
 | 
					 | 
				
			||||||
				     struct mgcp_conn * conn);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*! MGCP endpoint properties */
 | 
					 | 
				
			||||||
struct mgcp_endpoint_type {
 | 
					 | 
				
			||||||
	/*!< maximum number of connections */
 | 
					 | 
				
			||||||
	int max_conns;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*!< callback that defines how to dispatch incoming RTP data */
 | 
					 | 
				
			||||||
	mgcp_dispatch_rtp_cb dispatch_rtp_cb;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*! MGCP endpoint typeset */
 | 
					 | 
				
			||||||
struct mgcp_endpoint_typeset {
 | 
					 | 
				
			||||||
	struct mgcp_endpoint_type rtp;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*! static MGCP endpoint typeset (pre-initalized, read-only) */
 | 
					 | 
				
			||||||
extern const struct mgcp_endpoint_typeset ep_typeset;
 | 
					 | 
				
			||||||
@@ -1,321 +0,0 @@
 | 
				
			|||||||
/* MGCP Private Data */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
 | 
					 | 
				
			||||||
 * (C) 2009-2012 by On-Waves
 | 
					 | 
				
			||||||
 * All Rights Reserved
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is free software; you can redistribute it and/or modify
 | 
					 | 
				
			||||||
 * it under the terms of the GNU Affero General Public License as published by
 | 
					 | 
				
			||||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
					 | 
				
			||||||
 * (at your option) any later version.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is distributed in the hope that it will be useful,
 | 
					 | 
				
			||||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 | 
				
			||||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					 | 
				
			||||||
 * GNU Affero General Public License for more details.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * You should have received a copy of the GNU Affero General Public License
 | 
					 | 
				
			||||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#pragma once
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
#include <inttypes.h>
 | 
					 | 
				
			||||||
#include <osmocom/core/select.h>
 | 
					 | 
				
			||||||
#include <osmocom/mgcp/mgcp.h>
 | 
					 | 
				
			||||||
#include <osmocom/core/linuxlist.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define CI_UNUSED 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define CONN_ID_BTS 0
 | 
					 | 
				
			||||||
#define CONN_ID_NET 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum mgcp_trunk_type {
 | 
					 | 
				
			||||||
	MGCP_TRUNK_VIRTUAL,
 | 
					 | 
				
			||||||
	MGCP_TRUNK_E1,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct mgcp_rtp_stream_state {
 | 
					 | 
				
			||||||
	uint32_t ssrc;
 | 
					 | 
				
			||||||
	uint16_t last_seq;
 | 
					 | 
				
			||||||
	uint32_t last_timestamp;
 | 
					 | 
				
			||||||
	uint32_t err_ts_counter;
 | 
					 | 
				
			||||||
	int32_t last_tsdelta;
 | 
					 | 
				
			||||||
	uint32_t last_arrival_time;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct mgcp_rtp_state {
 | 
					 | 
				
			||||||
	int initialized;
 | 
					 | 
				
			||||||
	int patch_ssrc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	uint32_t orig_ssrc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int seq_offset;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int32_t  timestamp_offset;
 | 
					 | 
				
			||||||
	uint32_t packet_duration;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct mgcp_rtp_stream_state in_stream;
 | 
					 | 
				
			||||||
	struct mgcp_rtp_stream_state out_stream;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* jitter and packet loss calculation */
 | 
					 | 
				
			||||||
	int stats_initialized;
 | 
					 | 
				
			||||||
	uint16_t stats_base_seq;
 | 
					 | 
				
			||||||
	uint16_t stats_max_seq;
 | 
					 | 
				
			||||||
	uint32_t stats_ssrc;
 | 
					 | 
				
			||||||
	uint32_t stats_jitter;
 | 
					 | 
				
			||||||
	int32_t stats_transit;
 | 
					 | 
				
			||||||
	int stats_cycles;
 | 
					 | 
				
			||||||
	bool patched_first_rtp_payload; /* FIXME: drop this, see OS#2459 */
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct mgcp_rtp_codec {
 | 
					 | 
				
			||||||
	uint32_t rate;
 | 
					 | 
				
			||||||
	int channels;
 | 
					 | 
				
			||||||
	uint32_t frame_duration_num;
 | 
					 | 
				
			||||||
	uint32_t frame_duration_den;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int payload_type;
 | 
					 | 
				
			||||||
	char *audio_name;
 | 
					 | 
				
			||||||
	char *subtype_name;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct mgcp_rtp_end {
 | 
					 | 
				
			||||||
	/* statistics */
 | 
					 | 
				
			||||||
	unsigned int packets_rx;
 | 
					 | 
				
			||||||
	unsigned int octets_rx;
 | 
					 | 
				
			||||||
	unsigned int packets_tx;
 | 
					 | 
				
			||||||
	unsigned int octets_tx;
 | 
					 | 
				
			||||||
	unsigned int dropped_packets;
 | 
					 | 
				
			||||||
	struct in_addr addr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* in network byte order */
 | 
					 | 
				
			||||||
	int rtp_port, rtcp_port;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* audio codec information */
 | 
					 | 
				
			||||||
	struct mgcp_rtp_codec codec;
 | 
					 | 
				
			||||||
	struct mgcp_rtp_codec alt_codec; /* TODO/XXX: make it generic */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* per endpoint data */
 | 
					 | 
				
			||||||
	int  frames_per_packet;
 | 
					 | 
				
			||||||
	uint32_t packet_duration_ms;
 | 
					 | 
				
			||||||
	char *fmtp_extra;
 | 
					 | 
				
			||||||
	int output_enabled;
 | 
					 | 
				
			||||||
	int force_output_ptime;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* RTP patching */
 | 
					 | 
				
			||||||
	int force_constant_ssrc; /* -1: always, 0: don't, 1: once */
 | 
					 | 
				
			||||||
	int force_aligned_timing;
 | 
					 | 
				
			||||||
	void *rtp_process_data;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Each end has a separate socket for RTP and RTCP */
 | 
					 | 
				
			||||||
	struct osmo_fd rtp;
 | 
					 | 
				
			||||||
	struct osmo_fd rtcp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int local_port;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct mgcp_rtp_tap {
 | 
					 | 
				
			||||||
	int enabled;
 | 
					 | 
				
			||||||
	struct sockaddr_in forward;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct mgcp_lco {
 | 
					 | 
				
			||||||
	char *string;
 | 
					 | 
				
			||||||
	char *codec;
 | 
					 | 
				
			||||||
	int pkt_period_min; /* time in ms */
 | 
					 | 
				
			||||||
	int pkt_period_max; /* time in ms */
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Specific rtp connection type (see struct mgcp_conn_rtp) */
 | 
					 | 
				
			||||||
enum mgcp_conn_rtp_type {
 | 
					 | 
				
			||||||
	MGCP_RTP_DEFAULT	= 0,
 | 
					 | 
				
			||||||
	MGCP_OSMUX_BSC,
 | 
					 | 
				
			||||||
	MGCP_OSMUX_BSC_NAT,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <osmocom/mgcp/osmux.h>
 | 
					 | 
				
			||||||
struct mgcp_conn;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* MGCP connection (RTP) */
 | 
					 | 
				
			||||||
struct mgcp_conn_rtp {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Backpointer to conn struct */
 | 
					 | 
				
			||||||
	struct mgcp_conn *conn;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Specific connection type */
 | 
					 | 
				
			||||||
	enum mgcp_conn_rtp_type type;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Port status */
 | 
					 | 
				
			||||||
	struct mgcp_rtp_end end;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Sequence bits */
 | 
					 | 
				
			||||||
	struct mgcp_rtp_state state;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* taps for the rtp connection */
 | 
					 | 
				
			||||||
	struct mgcp_rtp_tap tap_in;
 | 
					 | 
				
			||||||
	struct mgcp_rtp_tap tap_out;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Osmux states (optional) */
 | 
					 | 
				
			||||||
	struct {
 | 
					 | 
				
			||||||
		/* Osmux state: disabled, activating, active */
 | 
					 | 
				
			||||||
		enum osmux_state state;
 | 
					 | 
				
			||||||
		/* Allocated Osmux circuit ID for this endpoint */
 | 
					 | 
				
			||||||
		int allocated_cid;
 | 
					 | 
				
			||||||
		/* Used Osmux circuit ID for this endpoint */
 | 
					 | 
				
			||||||
		uint8_t cid;
 | 
					 | 
				
			||||||
		/* handle to batch messages */
 | 
					 | 
				
			||||||
		struct osmux_in_handle *in;
 | 
					 | 
				
			||||||
		/* handle to unbatch messages */
 | 
					 | 
				
			||||||
		struct osmux_out_handle out;
 | 
					 | 
				
			||||||
		/* statistics */
 | 
					 | 
				
			||||||
		struct {
 | 
					 | 
				
			||||||
			uint32_t chunks;
 | 
					 | 
				
			||||||
			uint32_t octets;
 | 
					 | 
				
			||||||
		} stats;
 | 
					 | 
				
			||||||
	} osmux;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*! Connection type, specifies which member of the union "u" in mgcp_conn
 | 
					 | 
				
			||||||
 *  contains a useful connection description (currently only RTP) */
 | 
					 | 
				
			||||||
enum mgcp_conn_type {
 | 
					 | 
				
			||||||
	MGCP_CONN_TYPE_RTP,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*! MGCP connection (untyped) */
 | 
					 | 
				
			||||||
struct mgcp_conn {
 | 
					 | 
				
			||||||
	/*!< list head */
 | 
					 | 
				
			||||||
	struct llist_head entry;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*!< Backpointer to the endpoint where the conn belongs to */
 | 
					 | 
				
			||||||
	struct mgcp_endpoint *endp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*!< type of the connection (union) */
 | 
					 | 
				
			||||||
	enum mgcp_conn_type type;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*!< mode of the connection */
 | 
					 | 
				
			||||||
	enum mgcp_connection_mode mode;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*!< copy of the mode to restore the original setting (VTY) */
 | 
					 | 
				
			||||||
	enum mgcp_connection_mode mode_orig;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*!< connection id to identify the conntion */
 | 
					 | 
				
			||||||
	uint32_t id;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*!< human readable name (vty, logging) */
 | 
					 | 
				
			||||||
	char name[256];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*!< union with connection description */
 | 
					 | 
				
			||||||
	union {
 | 
					 | 
				
			||||||
		struct mgcp_conn_rtp rtp;
 | 
					 | 
				
			||||||
	} u;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*!< pointer to optional private data */
 | 
					 | 
				
			||||||
	void *priv;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <osmocom/mgcp/mgcp_conn.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct mgcp_endpoint_type;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct mgcp_endpoint {
 | 
					 | 
				
			||||||
	char *callid;
 | 
					 | 
				
			||||||
	struct mgcp_lco local_options;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct llist_head conns;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* backpointer */
 | 
					 | 
				
			||||||
	struct mgcp_config *cfg;
 | 
					 | 
				
			||||||
	struct mgcp_trunk_config *tcfg;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const struct mgcp_endpoint_type *type;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* fields for re-transmission */
 | 
					 | 
				
			||||||
	char *last_trans;
 | 
					 | 
				
			||||||
	char *last_response;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define ENDPOINT_NUMBER(endp) abs((int)(endp - endp->tcfg->endpoints))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Internal structure while parsing a request
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
struct mgcp_parse_data {
 | 
					 | 
				
			||||||
	struct mgcp_config *cfg;
 | 
					 | 
				
			||||||
	struct mgcp_endpoint *endp;
 | 
					 | 
				
			||||||
	char *trans;
 | 
					 | 
				
			||||||
	char *save;
 | 
					 | 
				
			||||||
	int found;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
 | 
					 | 
				
			||||||
	      char *buf, int rc, struct mgcp_conn_rtp *conn_src,
 | 
					 | 
				
			||||||
	      struct mgcp_conn_rtp *conn_dst);
 | 
					 | 
				
			||||||
int mgcp_send_dummy(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn);
 | 
					 | 
				
			||||||
int mgcp_dispatch_rtp_bridge_cb(int proto, struct sockaddr_in *addr, char *buf,
 | 
					 | 
				
			||||||
				unsigned int buf_size, struct mgcp_conn *conn);
 | 
					 | 
				
			||||||
int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port,
 | 
					 | 
				
			||||||
			   struct mgcp_conn_rtp *conn);
 | 
					 | 
				
			||||||
void mgcp_free_rtp_port(struct mgcp_rtp_end *end);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* For transcoding we need to manage an in and an output that are connected */
 | 
					 | 
				
			||||||
static inline int endp_back_channel(int endpoint)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return endpoint + 60;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct mgcp_trunk_config *mgcp_trunk_alloc(struct mgcp_config *cfg, int index);
 | 
					 | 
				
			||||||
struct mgcp_trunk_config *mgcp_trunk_num(struct mgcp_config *cfg, int index);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change,
 | 
					 | 
				
			||||||
			 struct mgcp_rtp_end *rtp);
 | 
					 | 
				
			||||||
uint32_t mgcp_rtp_packet_duration(struct mgcp_endpoint *endp,
 | 
					 | 
				
			||||||
				  struct mgcp_rtp_end *rtp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* payload processing default functions */
 | 
					 | 
				
			||||||
int mgcp_rtp_processing_default(struct mgcp_endpoint *endp, struct mgcp_rtp_end *dst_end,
 | 
					 | 
				
			||||||
				char *data, int *len, int buf_size);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int mgcp_setup_rtp_processing_default(struct mgcp_endpoint *endp,
 | 
					 | 
				
			||||||
				      struct mgcp_rtp_end *dst_end,
 | 
					 | 
				
			||||||
				      struct mgcp_rtp_end *src_end);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void mgcp_get_net_downlink_format_default(struct mgcp_endpoint *endp,
 | 
					 | 
				
			||||||
					  int *payload_type,
 | 
					 | 
				
			||||||
					  const char**audio_name,
 | 
					 | 
				
			||||||
					  const char**fmtp_extra,
 | 
					 | 
				
			||||||
					  struct mgcp_conn_rtp *conn);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* internal RTP Annex A counting */
 | 
					 | 
				
			||||||
void mgcp_rtp_annex_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *state,
 | 
					 | 
				
			||||||
			const uint16_t seq, const int32_t transit,
 | 
					 | 
				
			||||||
			const uint32_t ssrc);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int mgcp_set_ip_tos(int fd, int tos);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum {
 | 
					 | 
				
			||||||
	MGCP_DEST_NET = 0,
 | 
					 | 
				
			||||||
	MGCP_DEST_BTS,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define MGCP_DUMMY_LOAD 0x23
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * SDP related information
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
/* Assume audio frame length of 20ms */
 | 
					 | 
				
			||||||
#define DEFAULT_RTP_AUDIO_FRAME_DUR_NUM 20
 | 
					 | 
				
			||||||
#define DEFAULT_RTP_AUDIO_FRAME_DUR_DEN 1000
 | 
					 | 
				
			||||||
#define DEFAULT_RTP_AUDIO_PACKET_DURATION_MS 20
 | 
					 | 
				
			||||||
#define DEFAULT_RTP_AUDIO_DEFAULT_RATE  8000
 | 
					 | 
				
			||||||
#define DEFAULT_RTP_AUDIO_DEFAULT_CHANNELS 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define PTYPE_UNDEFINED (-1)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void mgcp_get_local_addr(char *addr, struct mgcp_conn_rtp *conn);
 | 
					 | 
				
			||||||
@@ -25,10 +25,12 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct mgcp_conn;
 | 
					struct mgcp_conn;
 | 
				
			||||||
struct mgcp_parse_data;
 | 
					struct mgcp_parse_data;
 | 
				
			||||||
struct mgcp_endpoint;
 | 
					struct mgcp_endpoint;
 | 
				
			||||||
 | 
					struct mgcp_trunk;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void mgcp_disp_msg(unsigned char *message, unsigned int len, char *preamble);
 | 
					void mgcp_disp_msg(unsigned char *message, unsigned int len, char *preamble);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -39,11 +41,11 @@ int mgcp_parse_header(struct mgcp_parse_data *pdata, char *data);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
int mgcp_parse_osmux_cid(const char *line);
 | 
					int mgcp_parse_osmux_cid(const char *line);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int mgcp_check_param(const struct mgcp_endpoint *endp, const char *line);
 | 
					bool mgcp_check_param(const struct mgcp_endpoint *endp, struct mgcp_trunk *trunk, const char *line);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int mgcp_verify_call_id(struct mgcp_endpoint *endp, const char *callid);
 | 
					int mgcp_verify_call_id(struct mgcp_endpoint *endp, const char *callid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int mgcp_verify_ci(struct mgcp_endpoint *endp, const char *ci);
 | 
					int mgcp_verify_ci(struct mgcp_endpoint *endp, const char *conn_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
char *mgcp_strline(char *str, char **saveptr);
 | 
					char *mgcp_strline(char *str, char **saveptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -54,5 +56,3 @@ char *mgcp_strline(char *str, char **saveptr);
 | 
				
			|||||||
#define for_each_non_empty_line(line, save)\
 | 
					#define for_each_non_empty_line(line, save)\
 | 
				
			||||||
	for (line = strtok_r(NULL, "\r\n", &save); line;\
 | 
						for (line = strtok_r(NULL, "\r\n", &save); line;\
 | 
				
			||||||
	     line = strtok_r(NULL, "\r\n", &save))
 | 
						     line = strtok_r(NULL, "\r\n", &save))
 | 
				
			||||||
 | 
					 | 
				
			||||||
int mgcp_parse_ci(uint32_t *conn_id, const char *ci);
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										179
									
								
								include/osmocom/mgcp/mgcp_network.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								include/osmocom/mgcp/mgcp_network.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,179 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <inttypes.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/core/socket.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/mgcp/mgcp.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* The following constant defines an RTP dummy payload that is used for
 | 
				
			||||||
 | 
					 * "UDP Hole Punching" (NAT) */
 | 
				
			||||||
 | 
					static const char rtp_dummy_payload[] = { 0x23 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Check if the data in a given message buffer matches the rtp dummy payload
 | 
				
			||||||
 | 
					 * defined above */
 | 
				
			||||||
 | 
					#define mgcp_is_rtp_dummy_payload(msg) \
 | 
				
			||||||
 | 
						(msgb_length(msg) == sizeof(rtp_dummy_payload) && \
 | 
				
			||||||
 | 
						memcmp(msgb_data(msg), rtp_dummy_payload, sizeof(rtp_dummy_payload)) == 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define RTP_BUF_SIZE	4096
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct mgcp_rtp_stream_state {
 | 
				
			||||||
 | 
						uint32_t ssrc;
 | 
				
			||||||
 | 
						uint16_t last_seq;
 | 
				
			||||||
 | 
						uint32_t last_timestamp;
 | 
				
			||||||
 | 
						struct rate_ctr *err_ts_ctr;
 | 
				
			||||||
 | 
						int32_t last_tsdelta;
 | 
				
			||||||
 | 
						uint32_t last_arrival_time;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct mgcp_rtp_state {
 | 
				
			||||||
 | 
						/* has this state structure been initialized? */
 | 
				
			||||||
 | 
						int initialized;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							/* are we patching the SSRC value? */
 | 
				
			||||||
 | 
							bool patch_ssrc;
 | 
				
			||||||
 | 
							/* original SSRC (to which we shall patch any different SSRC) */
 | 
				
			||||||
 | 
							uint32_t orig_ssrc;
 | 
				
			||||||
 | 
							/* offset to apply on the sequence number */
 | 
				
			||||||
 | 
							int seq_offset;
 | 
				
			||||||
 | 
							/* offset to apply on the timestamp number */
 | 
				
			||||||
 | 
							int32_t timestamp_offset;
 | 
				
			||||||
 | 
						} patch;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* duration of a packet (FIXME: in which unit?) */
 | 
				
			||||||
 | 
						uint32_t packet_duration;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Note: These states are not continuously updated, they serve as an
 | 
				
			||||||
 | 
						 * information source to patch certain values in the RTP header. Do
 | 
				
			||||||
 | 
						 * not use this state if constantly updated data about the RTP stream
 | 
				
			||||||
 | 
						 * is needed. (see also mgcp_patch_and_count() */
 | 
				
			||||||
 | 
						struct mgcp_rtp_stream_state in_stream;
 | 
				
			||||||
 | 
						struct mgcp_rtp_stream_state out_stream;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* jitter and packet loss calculation */
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							int initialized;
 | 
				
			||||||
 | 
							uint16_t base_seq;
 | 
				
			||||||
 | 
							uint16_t max_seq;
 | 
				
			||||||
 | 
							uint32_t ssrc;
 | 
				
			||||||
 | 
							uint32_t jitter;
 | 
				
			||||||
 | 
							int32_t transit;
 | 
				
			||||||
 | 
							int cycles;
 | 
				
			||||||
 | 
						} stats;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Alternative values for RTP tx, in case no sufficient header
 | 
				
			||||||
 | 
						 * information is available so the header needs to be generated
 | 
				
			||||||
 | 
						 * locally (when just forwarding packets, the header of incoming
 | 
				
			||||||
 | 
						 * data is just re-used) */
 | 
				
			||||||
 | 
						uint16_t alt_rtp_tx_sequence;
 | 
				
			||||||
 | 
						uint32_t alt_rtp_tx_ssrc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool patched_first_rtp_payload; /* FIXME: drop this, see OS#2459 */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct mgcp_rtp_codec {
 | 
				
			||||||
 | 
						uint32_t rate;
 | 
				
			||||||
 | 
						int channels;
 | 
				
			||||||
 | 
						uint32_t frame_duration_num;
 | 
				
			||||||
 | 
						uint32_t frame_duration_den;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int payload_type;
 | 
				
			||||||
 | 
						char audio_name[64];
 | 
				
			||||||
 | 
						char subtype_name[64];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool param_present;
 | 
				
			||||||
 | 
						struct mgcp_codec_param param;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 'mgcp_rtp_end': basically a wrapper around the RTP+RTCP ports */
 | 
				
			||||||
 | 
					struct mgcp_rtp_end {
 | 
				
			||||||
 | 
						/* remote IP address of the RTP socket */
 | 
				
			||||||
 | 
						struct osmo_sockaddr addr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* in network byte order */
 | 
				
			||||||
 | 
						int rtp_port, rtcp_port;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* currently selected audio codec */
 | 
				
			||||||
 | 
						struct mgcp_rtp_codec *codec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* array with assigned audio codecs to choose from (SDP) */
 | 
				
			||||||
 | 
						struct mgcp_rtp_codec codecs[MGCP_MAX_CODECS];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* number of assigned audio codecs (SDP) */
 | 
				
			||||||
 | 
						unsigned int codecs_assigned;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* per endpoint data */
 | 
				
			||||||
 | 
						int  frames_per_packet;
 | 
				
			||||||
 | 
						uint32_t packet_duration_ms;
 | 
				
			||||||
 | 
						int maximum_packet_time; /* -1: not set */
 | 
				
			||||||
 | 
						char *fmtp_extra;
 | 
				
			||||||
 | 
						/* are we transmitting packets (1) or dropping (0) outbound packets */
 | 
				
			||||||
 | 
						int output_enabled;
 | 
				
			||||||
 | 
						/* FIXME: This parameter can be set + printed, but is nowhere used! */
 | 
				
			||||||
 | 
						int force_output_ptime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* RTP patching */
 | 
				
			||||||
 | 
						int force_constant_ssrc; /* -1: always, 0: don't, 1: once */
 | 
				
			||||||
 | 
						/* should we perform align_rtp_timestamp_offset() (1) or not (0) */
 | 
				
			||||||
 | 
						int force_aligned_timing;
 | 
				
			||||||
 | 
						bool rfc5993_hr_convert;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Each end has a separate socket for RTP and RTCP */
 | 
				
			||||||
 | 
						struct osmo_fd rtp;
 | 
				
			||||||
 | 
						struct osmo_fd rtcp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* local UDP port number of the RTP socket; RTCP is +1 */
 | 
				
			||||||
 | 
						int local_port;
 | 
				
			||||||
 | 
						/* where the endpoint RTP connection binds to, set during CRCX and
 | 
				
			||||||
 | 
						 * possibly updated during MDCX */
 | 
				
			||||||
 | 
						char local_addr[INET6_ADDRSTRLEN];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool mgcp_rtp_end_remote_addr_available(const struct mgcp_rtp_end *rtp_end);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct mgcp_rtp_tap {
 | 
				
			||||||
 | 
						/* is this tap active (1) or not (0) */
 | 
				
			||||||
 | 
						int enabled;
 | 
				
			||||||
 | 
						/* IP/port to which we're forwarding the tapped data */
 | 
				
			||||||
 | 
						struct osmo_sockaddr forward;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct mgcp_conn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct osmo_sockaddr *addr,
 | 
				
			||||||
 | 
						      struct msgb *msg, struct mgcp_conn_rtp *conn_src,
 | 
				
			||||||
 | 
						      struct mgcp_conn_rtp *conn_dst);
 | 
				
			||||||
 | 
					int mgcp_send_dummy(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn);
 | 
				
			||||||
 | 
					int mgcp_dispatch_rtp_bridge_cb(struct msgb *msg);
 | 
				
			||||||
 | 
					void mgcp_cleanup_rtp_bridge_cb(struct mgcp_endpoint *endp, struct mgcp_conn *conn);
 | 
				
			||||||
 | 
					int mgcp_dispatch_e1_bridge_cb(struct msgb *msg);
 | 
				
			||||||
 | 
					void mgcp_cleanup_e1_bridge_cb(struct mgcp_endpoint *endp, struct mgcp_conn *conn);
 | 
				
			||||||
 | 
					int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port,
 | 
				
			||||||
 | 
								   struct mgcp_conn_rtp *conn);
 | 
				
			||||||
 | 
					void mgcp_free_rtp_port(struct mgcp_rtp_end *end);
 | 
				
			||||||
 | 
					void mgcp_patch_and_count(const struct mgcp_endpoint *endp,
 | 
				
			||||||
 | 
								  struct mgcp_rtp_state *state,
 | 
				
			||||||
 | 
								  struct mgcp_rtp_end *rtp_end,
 | 
				
			||||||
 | 
								  struct osmo_sockaddr *addr, struct msgb *msg);
 | 
				
			||||||
 | 
					void mgcp_get_local_addr(char *addr, struct mgcp_conn_rtp *conn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* payload processing default functions */
 | 
				
			||||||
 | 
					int mgcp_rtp_processing_default(struct mgcp_endpoint *endp, struct mgcp_rtp_end *dst_end,
 | 
				
			||||||
 | 
									char *data, int *len, int buf_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int mgcp_setup_rtp_processing_default(struct mgcp_endpoint *endp,
 | 
				
			||||||
 | 
									      struct mgcp_conn_rtp *conn_dst,
 | 
				
			||||||
 | 
									      struct mgcp_conn_rtp *conn_src);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void mgcp_get_net_downlink_format_default(struct mgcp_endpoint *endp,
 | 
				
			||||||
 | 
										  const struct mgcp_rtp_codec **codec,
 | 
				
			||||||
 | 
										  const char **fmtp_extra,
 | 
				
			||||||
 | 
										  struct mgcp_conn_rtp *conn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* internal RTP Annex A counting */
 | 
				
			||||||
 | 
					void mgcp_rtp_annex_count(const struct mgcp_endpoint *endp, struct mgcp_rtp_state *state,
 | 
				
			||||||
 | 
								const uint16_t seq, const int32_t transit,
 | 
				
			||||||
 | 
								const uint32_t ssrc, const bool marker_bit);
 | 
				
			||||||
							
								
								
									
										30
									
								
								include/osmocom/mgcp/mgcp_protocol.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								include/osmocom/mgcp/mgcp_protocol.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Internal structure while parsing a request */
 | 
				
			||||||
 | 
					struct mgcp_parse_data {
 | 
				
			||||||
 | 
						struct mgcp_config *cfg;
 | 
				
			||||||
 | 
						char *epname;
 | 
				
			||||||
 | 
						char *trans;
 | 
				
			||||||
 | 
						char *save;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Local connection options */
 | 
				
			||||||
 | 
					struct mgcp_lco {
 | 
				
			||||||
 | 
						char *string;
 | 
				
			||||||
 | 
						char *codec;
 | 
				
			||||||
 | 
						int pkt_period_min; /* time in ms */
 | 
				
			||||||
 | 
						int pkt_period_max; /* time in ms */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char *mgcp_debug_get_last_endpoint_name(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char *get_lco_identifier(const char *options);
 | 
				
			||||||
 | 
					int check_local_cx_options(void *ctx, const char *options);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct mgcp_rtp_end;
 | 
				
			||||||
 | 
					struct mgcp_endpoint;
 | 
				
			||||||
 | 
					void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change,
 | 
				
			||||||
 | 
								 struct mgcp_rtp_end *rtp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t mgcp_rtp_packet_duration(const struct mgcp_endpoint *endp,
 | 
				
			||||||
 | 
									  const struct mgcp_rtp_end *rtp);
 | 
				
			||||||
							
								
								
									
										107
									
								
								include/osmocom/mgcp/mgcp_ratectr.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								include/osmocom/mgcp/mgcp_ratectr.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,107 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Global MCGP general rate counters */
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						MGCP_GENERAL_RX_MSGS_TOTAL,
 | 
				
			||||||
 | 
						MGCP_GENERAL_RX_MSGS_RETRANSMITTED,
 | 
				
			||||||
 | 
						MGCP_GENERAL_RX_MSGS_HANDLED,
 | 
				
			||||||
 | 
						MGCP_GENERAL_RX_MSGS_UNHANDLED,
 | 
				
			||||||
 | 
						MGCP_GENERAL_RX_FAIL_MSG_PARSE,
 | 
				
			||||||
 | 
						MGCP_GENERAL_RX_FAIL_NO_ENDPOINT,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Trunk-global MCGP CRCX related rate counters */
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						MGCP_CRCX_SUCCESS,
 | 
				
			||||||
 | 
						MGCP_CRCX_FAIL_BAD_ACTION,
 | 
				
			||||||
 | 
						MGCP_CRCX_FAIL_UNHANDLED_PARAM,
 | 
				
			||||||
 | 
						MGCP_CRCX_FAIL_MISSING_CALLID,
 | 
				
			||||||
 | 
						MGCP_CRCX_FAIL_INVALID_MODE,
 | 
				
			||||||
 | 
						MGCP_CRCX_FAIL_LIMIT_EXCEEDED,
 | 
				
			||||||
 | 
						MGCP_CRCX_FAIL_UNKNOWN_CALLID,
 | 
				
			||||||
 | 
						MGCP_CRCX_FAIL_ALLOC_CONN,
 | 
				
			||||||
 | 
						MGCP_CRCX_FAIL_NO_REMOTE_CONN_DESC,
 | 
				
			||||||
 | 
						MGCP_CRCX_FAIL_START_RTP,
 | 
				
			||||||
 | 
						MGCP_CRCX_FAIL_NO_OSMUX,
 | 
				
			||||||
 | 
						MGCP_CRCX_FAIL_INVALID_CONN_OPTIONS,
 | 
				
			||||||
 | 
						MGCP_CRCX_FAIL_CODEC_NEGOTIATION,
 | 
				
			||||||
 | 
						MGCP_CRCX_FAIL_BIND_PORT,
 | 
				
			||||||
 | 
						MGCP_CRCX_FAIL_AVAIL,
 | 
				
			||||||
 | 
						MGCP_CRCX_FAIL_CLAIM,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Trunk-global MCGP MDCX related rate counters */
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						MGCP_MDCX_SUCCESS,
 | 
				
			||||||
 | 
						MGCP_MDCX_FAIL_WILDCARD,
 | 
				
			||||||
 | 
						MGCP_MDCX_FAIL_NO_CONN,
 | 
				
			||||||
 | 
						MGCP_MDCX_FAIL_INVALID_CALLID,
 | 
				
			||||||
 | 
						MGCP_MDCX_FAIL_INVALID_CONNID,
 | 
				
			||||||
 | 
						MGCP_MDCX_FAIL_UNHANDLED_PARAM,
 | 
				
			||||||
 | 
						MGCP_MDCX_FAIL_NO_CONNID,
 | 
				
			||||||
 | 
						MGCP_MDCX_FAIL_CONN_NOT_FOUND,
 | 
				
			||||||
 | 
						MGCP_MDCX_FAIL_INVALID_MODE,
 | 
				
			||||||
 | 
						MGCP_MDCX_FAIL_INVALID_CONN_OPTIONS,
 | 
				
			||||||
 | 
						MGCP_MDCX_FAIL_NO_REMOTE_CONN_DESC,
 | 
				
			||||||
 | 
						MGCP_MDCX_FAIL_START_RTP,
 | 
				
			||||||
 | 
						MGCP_MDCX_FAIL_AVAIL,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Trunk-global MCGP DLCX related rate counters */
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						MGCP_DLCX_SUCCESS,
 | 
				
			||||||
 | 
						MGCP_DLCX_FAIL_NO_CONN,
 | 
				
			||||||
 | 
						MGCP_DLCX_FAIL_INVALID_CALLID,
 | 
				
			||||||
 | 
						MGCP_DLCX_FAIL_INVALID_CONNID,
 | 
				
			||||||
 | 
						MGCP_DLCX_FAIL_UNHANDLED_PARAM,
 | 
				
			||||||
 | 
						MGCP_DLCX_FAIL_AVAIL,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Trunk-global E1 related counters */
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
					        E1_I460_TRAU_RX_FAIL_CTR,
 | 
				
			||||||
 | 
					        E1_I460_TRAU_TX_FAIL_CTR,
 | 
				
			||||||
 | 
					        E1_I460_TRAU_MUX_EMPTY_CTR,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* NOTE: When adding counters, also the dump_ratectr_* routines in vty.c must be updated. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct mgcp_ratectr_global {
 | 
				
			||||||
 | 
						/* Rate counter group which contains stats for generic MGCP events. */
 | 
				
			||||||
 | 
						struct rate_ctr_group *mgcp_general_ctr_group;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct mgcp_ratectr_trunk {
 | 
				
			||||||
 | 
						/* Rate counter group which contains stats for processed CRCX commands. */
 | 
				
			||||||
 | 
						struct rate_ctr_group *mgcp_crcx_ctr_group;
 | 
				
			||||||
 | 
						/* Rate counter group which contains stats for processed MDCX commands. */
 | 
				
			||||||
 | 
						struct rate_ctr_group *mgcp_mdcx_ctr_group;
 | 
				
			||||||
 | 
						/* Rate counter group which contains stats for processed DLCX commands. */
 | 
				
			||||||
 | 
						struct rate_ctr_group *mgcp_dlcx_ctr_group;
 | 
				
			||||||
 | 
						/* Rate counter group which aggregates stats of individual RTP connections. */
 | 
				
			||||||
 | 
						struct rate_ctr_group *all_rtp_conn_stats;
 | 
				
			||||||
 | 
						/* Rate counter group which contains stats for E1 events (only valid for E1 trunks) */
 | 
				
			||||||
 | 
						struct rate_ctr_group *e1_stats;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct mgcp_config;
 | 
				
			||||||
 | 
					struct mgcp_trunk;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int mgcp_ratectr_global_alloc(struct mgcp_config *cfg);
 | 
				
			||||||
 | 
					void mgcp_ratectr_global_free(struct mgcp_config *cfg);
 | 
				
			||||||
 | 
					int mgcp_ratectr_trunk_alloc(struct mgcp_trunk *trunk);
 | 
				
			||||||
 | 
					void mgcp_ratectr_trunk_free(struct mgcp_trunk *trunk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Trunk-global common stat items */
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						TRUNK_STAT_ENDPOINTS_TOTAL,
 | 
				
			||||||
 | 
						TRUNK_STAT_ENDPOINTS_USED,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct mgcp_stat_trunk {
 | 
				
			||||||
 | 
						/* Stat item group which contains general status values of the trunk. */
 | 
				
			||||||
 | 
						struct osmo_stat_item_group *common;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int mgcp_stat_trunk_alloc(struct mgcp_trunk *trunk);
 | 
				
			||||||
 | 
					void mgcp_stat_trunk_free(struct mgcp_trunk *trunk);
 | 
				
			||||||
@@ -21,15 +21,11 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
#include <osmocom/mgcp/mgcp_sdp.h>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
int mgcp_parse_sdp_data(const struct mgcp_endpoint *endp,
 | 
					int mgcp_parse_sdp_data(const struct mgcp_endpoint *endp,
 | 
				
			||||||
			struct mgcp_conn_rtp *conn,
 | 
								struct mgcp_conn_rtp *conn,
 | 
				
			||||||
			struct mgcp_parse_data *p);
 | 
								struct mgcp_parse_data *p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int mgcp_set_audio_info(void *ctx, struct mgcp_rtp_codec *codec,
 | 
					 | 
				
			||||||
			int payload_type, const char *audio_name);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int mgcp_write_response_sdp(const struct mgcp_endpoint *endp,
 | 
					int mgcp_write_response_sdp(const struct mgcp_endpoint *endp,
 | 
				
			||||||
			    const struct mgcp_conn_rtp *conn, struct msgb *sdp,
 | 
								    const struct mgcp_conn_rtp *conn, struct msgb *sdp,
 | 
				
			||||||
			    const char *addr);
 | 
								    const char *addr);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,14 +24,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <osmocom/mgcp/mgcp_internal.h>
 | 
					 | 
				
			||||||
#include <inttypes.h>
 | 
					#include <inttypes.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void mgcp_format_stats(char *str, size_t str_len,  struct mgcp_conn *conn);
 | 
					void mgcp_format_stats(char *str, size_t str_len,  struct mgcp_conn *conn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Exposed for test purposes only, do not use actively */
 | 
					/* Exposed for test purposes only, do not use actively */
 | 
				
			||||||
void calc_loss(struct mgcp_rtp_state *s, struct mgcp_rtp_end *,
 | 
					void calc_loss(struct mgcp_conn_rtp *conn, uint32_t *expected, int *loss);
 | 
				
			||||||
			uint32_t *expected, int *loss);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Exposed for test purposes only, do not use actively */
 | 
					/* Exposed for test purposes only, do not use actively */
 | 
				
			||||||
uint32_t calc_jitter(struct mgcp_rtp_state *);
 | 
					uint32_t calc_jitter(struct mgcp_rtp_state *);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										88
									
								
								include/osmocom/mgcp/mgcp_trunk.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								include/osmocom/mgcp/mgcp_trunk.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,88 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/gsm/i460_mux.h>
 | 
				
			||||||
 | 
					#include <osmocom/abis/e1_input.h>
 | 
				
			||||||
 | 
					#include <osmocom/mgcp/mgcp_ratectr.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LOGPTRUNK(trunk, cat, level, fmt, args...) \
 | 
				
			||||||
 | 
					LOGP(cat, level, "trunk:%u " fmt, \
 | 
				
			||||||
 | 
					     trunk ? trunk->trunk_nr : 0, \
 | 
				
			||||||
 | 
					     ## args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum mgcp_trunk_type {
 | 
				
			||||||
 | 
						MGCP_TRUNK_VIRTUAL,
 | 
				
			||||||
 | 
						MGCP_TRUNK_E1,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern const struct value_string mgcp_trunk_type_strs[];
 | 
				
			||||||
 | 
					static inline const char *mgcp_trunk_type_strs_str(enum mgcp_trunk_type val)
 | 
				
			||||||
 | 
					{ return get_value_string(mgcp_trunk_type_strs, val); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct mgcp_trunk {
 | 
				
			||||||
 | 
						struct llist_head entry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct mgcp_config *cfg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						unsigned int trunk_nr;
 | 
				
			||||||
 | 
						enum mgcp_trunk_type trunk_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						char *audio_fmtp_extra;
 | 
				
			||||||
 | 
						int audio_send_ptime;
 | 
				
			||||||
 | 
						int audio_send_name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int no_audio_transcoding;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int omit_rtcp;
 | 
				
			||||||
 | 
						int keepalive_interval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* RTP patching */
 | 
				
			||||||
 | 
						int force_constant_ssrc; /* 0: don't, 1: once */
 | 
				
			||||||
 | 
						int force_aligned_timing;
 | 
				
			||||||
 | 
						bool rfc5993_hr_convert;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* spec handling */
 | 
				
			||||||
 | 
						int force_realloc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* timer */
 | 
				
			||||||
 | 
						struct osmo_timer_list keepalive_timer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* When set, incoming RTP packets are not filtered
 | 
				
			||||||
 | 
						 * when ports and ip-address do not match (debug) */
 | 
				
			||||||
 | 
						int rtp_accept_all;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						unsigned int number_endpoints;
 | 
				
			||||||
 | 
						struct mgcp_endpoint **endpoints;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* rate counters and stat items to measure the trunks overall performance and health */
 | 
				
			||||||
 | 
						struct mgcp_ratectr_trunk ratectr;
 | 
				
			||||||
 | 
						struct mgcp_stat_trunk stats;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						union {
 | 
				
			||||||
 | 
							/* Virtual trunk specific */
 | 
				
			||||||
 | 
							struct {
 | 
				
			||||||
 | 
								unsigned int vty_number_endpoints;
 | 
				
			||||||
 | 
							} v;
 | 
				
			||||||
 | 
							/* E1 specific */
 | 
				
			||||||
 | 
							struct {
 | 
				
			||||||
 | 
								unsigned int vty_line_nr;
 | 
				
			||||||
 | 
								bool ts_in_use[NUM_E1_TS-1];
 | 
				
			||||||
 | 
								struct osmo_i460_timeslot i460_ts[NUM_E1_TS-1];
 | 
				
			||||||
 | 
								/* Note: on an E1 line TS 0 is devoted to framing and
 | 
				
			||||||
 | 
								 * alignment and therefore only NUM_E1_TS-1 timeslots
 | 
				
			||||||
 | 
								 * are available for traffic. */
 | 
				
			||||||
 | 
							} e1;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct mgcp_trunk *mgcp_trunk_alloc(struct mgcp_config *cfg, enum mgcp_trunk_type ttype, unsigned int nr);
 | 
				
			||||||
 | 
					int mgcp_trunk_equip(struct mgcp_trunk *trunk);
 | 
				
			||||||
 | 
					struct mgcp_trunk *mgcp_trunk_by_num(const struct mgcp_config *cfg, enum mgcp_trunk_type ttype, unsigned int nr);
 | 
				
			||||||
 | 
					struct mgcp_trunk *mgcp_trunk_by_name(const struct mgcp_config *cfg, const char *epname);
 | 
				
			||||||
 | 
					int e1_trunk_nr_from_epname(unsigned int *trunk_nr, const char *epname);
 | 
				
			||||||
 | 
					struct mgcp_trunk *mgcp_trunk_by_line_num(const struct mgcp_config *cfg, unsigned int num);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* The virtual trunk is always created on trunk id 0 for historical reasons,
 | 
				
			||||||
 | 
					 * use this define constant as ID when allocating a virtual trunk. Other
 | 
				
			||||||
 | 
					 * trunks may be assigned with arbritrary id numbers */
 | 
				
			||||||
 | 
					#define MGCP_VIRT_TRUNK_ID 0
 | 
				
			||||||
@@ -1,5 +1,6 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/core/socket.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <osmocom/netif/osmux.h>
 | 
					#include <osmocom/netif/osmux.h>
 | 
				
			||||||
struct mgcp_conn_rtp;
 | 
					struct mgcp_conn_rtp;
 | 
				
			||||||
@@ -13,21 +14,23 @@ enum {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
int osmux_init(int role, struct mgcp_config *cfg);
 | 
					int osmux_init(int role, struct mgcp_config *cfg);
 | 
				
			||||||
int osmux_enable_conn(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn,
 | 
					int osmux_enable_conn(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn,
 | 
				
			||||||
		      struct in_addr *addr, uint16_t port);
 | 
							      struct osmo_sockaddr *addr, uint16_t port);
 | 
				
			||||||
void osmux_disable_conn(struct mgcp_conn_rtp *conn);
 | 
					void conn_osmux_disable(struct mgcp_conn_rtp *conn);
 | 
				
			||||||
void osmux_allocate_cid(struct mgcp_conn_rtp *conn);
 | 
					int conn_osmux_allocate_cid(struct mgcp_conn_rtp *conn, int osmux_cid);
 | 
				
			||||||
void osmux_release_cid(struct mgcp_conn_rtp *conn);
 | 
					void conn_osmux_release_cid(struct mgcp_conn_rtp *conn);
 | 
				
			||||||
int osmux_xfrm_to_osmux(char *buf, int buf_len, struct mgcp_conn_rtp *conn);
 | 
					int osmux_xfrm_to_osmux(char *buf, int buf_len, struct mgcp_conn_rtp *conn);
 | 
				
			||||||
int osmux_send_dummy(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn);
 | 
					int osmux_send_dummy(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn);
 | 
				
			||||||
int osmux_get_cid(void);
 | 
					
 | 
				
			||||||
void osmux_put_cid(uint8_t osmux_cid);
 | 
					void osmux_cid_pool_get(uint8_t osmux_cid);
 | 
				
			||||||
int osmux_used_cid(void);
 | 
					int osmux_cid_pool_get_next(void);
 | 
				
			||||||
 | 
					void osmux_cid_pool_put(uint8_t osmux_cid);
 | 
				
			||||||
 | 
					bool osmux_cid_pool_allocated(uint8_t osmux_cid);
 | 
				
			||||||
 | 
					int osmux_cid_pool_count_used(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum osmux_state {
 | 
					enum osmux_state {
 | 
				
			||||||
	OSMUX_STATE_DISABLED = 0,
 | 
						OSMUX_STATE_DISABLED = 0, /* Osmux not being currently used by endp */
 | 
				
			||||||
	OSMUX_STATE_NEGOTIATING,
 | 
						OSMUX_STATE_ACTIVATING,   /* Osmux was accepted in MGCP CRCX ACK. It can now be enabled by \ref osmux_enable_endpoint. */
 | 
				
			||||||
	OSMUX_STATE_ACTIVATING,
 | 
						OSMUX_STATE_ENABLED,	  /* Osmux was initialized by \ref osmux_enable_endpoint and can process frames */
 | 
				
			||||||
	OSMUX_STATE_ENABLED,
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum osmux_usage {
 | 
					enum osmux_usage {
 | 
				
			||||||
@@ -35,4 +38,3 @@ enum osmux_usage {
 | 
				
			|||||||
	OSMUX_USAGE_ON = 1,
 | 
						OSMUX_USAGE_ON = 1,
 | 
				
			||||||
	OSMUX_USAGE_ONLY = 2,
 | 
						OSMUX_USAGE_ONLY = 2,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,31 +1,12 @@
 | 
				
			|||||||
#ifndef OPENBSC_VTY_H
 | 
					#pragma once
 | 
				
			||||||
#define OPENBSC_VTY_H
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <osmocom/vty/vty.h>
 | 
					 | 
				
			||||||
#include <osmocom/vty/buffer.h>
 | 
					 | 
				
			||||||
#include <osmocom/vty/command.h>
 | 
					#include <osmocom/vty/command.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct gsm_network;
 | 
					 | 
				
			||||||
struct vty;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void openbsc_vty_print_statistics(struct vty *vty, struct gsm_network *);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct buffer *vty_argv_to_buffer(int argc, const char *argv[], int base);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern struct cmd_element cfg_description_cmd;
 | 
					 | 
				
			||||||
extern struct cmd_element cfg_no_description_cmd;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum mgcp_vty_node {
 | 
					enum mgcp_vty_node {
 | 
				
			||||||
	MGCP_NODE = _LAST_OSMOVTY_NODE + 1,
 | 
						MGCP_NODE = _LAST_OSMOVTY_NODE + 1,
 | 
				
			||||||
	TRUNK_NODE,
 | 
						TRUNK_NODE,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct log_info;
 | 
					enum mgw_vty_cmd_attr {
 | 
				
			||||||
int bsc_vty_init(struct gsm_network *network);
 | 
						MGW_CMD_ATTR_NEWCONN = 0,
 | 
				
			||||||
int bsc_vty_init_extra(void);
 | 
					};
 | 
				
			||||||
 | 
					 | 
				
			||||||
void msc_vty_init(struct gsm_network *msc_network);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct gsm_network *gsmnet_from_vty(struct vty *vty);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,7 @@ BUILT_SOURCES = \
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
noinst_HEADERS = \
 | 
					noinst_HEADERS = \
 | 
				
			||||||
	mgcp_client_internal.h \
 | 
						mgcp_client_internal.h \
 | 
				
			||||||
 | 
						mgcp_client_pool_internal.h \
 | 
				
			||||||
	$(NULL)
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mgcp_common.h: $(top_srcdir)/include/osmocom/mgcp/mgcp_common.h
 | 
					mgcp_common.h: $(top_srcdir)/include/osmocom/mgcp/mgcp_common.h
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,11 +5,14 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <osmocom/mgcp_client/mgcp_common.h>
 | 
					#include <osmocom/mgcp_client/mgcp_common.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MGCP_CLIENT_LOCAL_ADDR_DEFAULT "0.0.0.0"
 | 
					/* See also: RFC 3435, chapter 3.5 Transmission over UDP */
 | 
				
			||||||
#define MGCP_CLIENT_LOCAL_PORT_DEFAULT 0
 | 
					#define MGCP_CLIENT_LOCAL_ADDR_DEFAULT NULL /* INADDR(6)_ANY */
 | 
				
			||||||
 | 
					#define MGCP_CLIENT_LOCAL_PORT_DEFAULT 2727
 | 
				
			||||||
#define MGCP_CLIENT_REMOTE_ADDR_DEFAULT "127.0.0.1"
 | 
					#define MGCP_CLIENT_REMOTE_ADDR_DEFAULT "127.0.0.1"
 | 
				
			||||||
#define MGCP_CLIENT_REMOTE_PORT_DEFAULT 2427
 | 
					#define MGCP_CLIENT_REMOTE_PORT_DEFAULT 2427
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MGCP_CLIENT_MGW_STR "Configure MGCP connection to Media Gateway\n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct msgb;
 | 
					struct msgb;
 | 
				
			||||||
struct vty;
 | 
					struct vty;
 | 
				
			||||||
struct mgcp_client;
 | 
					struct mgcp_client;
 | 
				
			||||||
@@ -19,24 +22,74 @@ struct mgcp_client_conf {
 | 
				
			|||||||
	int local_port;
 | 
						int local_port;
 | 
				
			||||||
	const char *remote_addr;
 | 
						const char *remote_addr;
 | 
				
			||||||
	int remote_port;
 | 
						int remote_port;
 | 
				
			||||||
	uint16_t first_endpoint;
 | 
					
 | 
				
			||||||
	uint16_t last_endpoint;
 | 
						/* By default, we are always addressing the MGW with e.g. 'rtpbridge/123@mgw'.
 | 
				
			||||||
	uint16_t bts_base;
 | 
						 * If this is nonempty, the contained name will be used instead of 'mgw'. */
 | 
				
			||||||
 | 
						char endpoint_domain_name[MGCP_ENDPOINT_MAXLEN];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* The user may configure certain endpoint names that are reset via DLCX
 | 
				
			||||||
 | 
						 * on startup. Usually this will be one wildcarded endpoint e.g.
 | 
				
			||||||
 | 
						 * 'rtpbridge/(wildcard)' or a number of specific E1 like e.g.
 | 
				
			||||||
 | 
						 * 'ds/e1-0/s-3/su16-4' */
 | 
				
			||||||
 | 
						struct llist_head reset_epnames;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* human readable name / description */
 | 
				
			||||||
 | 
						char *description;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef unsigned int mgcp_trans_id_t;
 | 
					typedef unsigned int mgcp_trans_id_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! Enumeration of the codec types that mgcp_client is able to handle. */
 | 
				
			||||||
 | 
					enum mgcp_codecs {
 | 
				
			||||||
 | 
						CODEC_PCMU_8000_1 = 0,
 | 
				
			||||||
 | 
						CODEC_GSM_8000_1 = 3,
 | 
				
			||||||
 | 
						CODEC_PCMA_8000_1 = 8,
 | 
				
			||||||
 | 
						CODEC_G729_8000_1 = 18,
 | 
				
			||||||
 | 
						CODEC_GSMEFR_8000_1 = 110,
 | 
				
			||||||
 | 
						CODEC_GSMHR_8000_1 = 111,
 | 
				
			||||||
 | 
						CODEC_AMR_8000_1 = 112,
 | 
				
			||||||
 | 
						CODEC_AMRWB_16000_1 = 113,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					/* Note: when new codec types are added, the corresponding value strings
 | 
				
			||||||
 | 
					 * in mgcp_client.c (codec_table) must be updated as well. Enumerations
 | 
				
			||||||
 | 
					 * in enum mgcp_codecs must correspond to a valid payload type. However,
 | 
				
			||||||
 | 
					 * this is an internal assumption that is made to avoid lookup tables.
 | 
				
			||||||
 | 
					 * The API-User should not rely on this coincidence! */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern const struct value_string osmo_mgcpc_codec_names[];
 | 
				
			||||||
 | 
					static inline const char *osmo_mgcpc_codec_name(enum mgcp_codecs val)
 | 
				
			||||||
 | 
					{ return get_value_string(osmo_mgcpc_codec_names, val); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! Structure to build a payload type map to allow the defiition custom payload
 | 
				
			||||||
 | 
					 *  types. */
 | 
				
			||||||
 | 
					struct ptmap {
 | 
				
			||||||
 | 
						/*! codec for which a payload type number should be defined */
 | 
				
			||||||
 | 
						enum mgcp_codecs codec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! payload type number (96-127) */
 | 
				
			||||||
 | 
						unsigned int pt;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct mgcp_response_head {
 | 
					struct mgcp_response_head {
 | 
				
			||||||
	int response_code;
 | 
						int response_code;
 | 
				
			||||||
	mgcp_trans_id_t trans_id;
 | 
						mgcp_trans_id_t trans_id;
 | 
				
			||||||
       const char *comment;
 | 
						char comment[MGCP_COMMENT_MAXLEN];
 | 
				
			||||||
 | 
						char conn_id[MGCP_CONN_ID_MAXLEN];
 | 
				
			||||||
 | 
						char endpoint[MGCP_ENDPOINT_MAXLEN];
 | 
				
			||||||
 | 
						bool x_osmo_osmux_use;
 | 
				
			||||||
 | 
						uint8_t x_osmo_osmux_cid;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct mgcp_response {
 | 
					struct mgcp_response {
 | 
				
			||||||
	char *body;
 | 
						char *body;
 | 
				
			||||||
	struct mgcp_response_head head;
 | 
						struct mgcp_response_head head;
 | 
				
			||||||
	uint16_t audio_port;
 | 
						uint16_t audio_port;
 | 
				
			||||||
	char audio_ip[INET_ADDRSTRLEN];
 | 
						char audio_ip[INET6_ADDRSTRLEN];
 | 
				
			||||||
 | 
						unsigned int ptime;
 | 
				
			||||||
 | 
						enum mgcp_codecs codecs[MGCP_MAX_CODECS];
 | 
				
			||||||
 | 
						unsigned int codecs_len;
 | 
				
			||||||
 | 
						struct ptmap ptmap[MGCP_MAX_CODECS];
 | 
				
			||||||
 | 
						unsigned int ptmap_len;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum mgcp_verb {
 | 
					enum mgcp_verb {
 | 
				
			||||||
@@ -53,9 +106,8 @@ enum mgcp_verb {
 | 
				
			|||||||
#define MGCP_MSG_PRESENCE_AUDIO_IP	0x0008
 | 
					#define MGCP_MSG_PRESENCE_AUDIO_IP	0x0008
 | 
				
			||||||
#define MGCP_MSG_PRESENCE_AUDIO_PORT	0x0010
 | 
					#define MGCP_MSG_PRESENCE_AUDIO_PORT	0x0010
 | 
				
			||||||
#define MGCP_MSG_PRESENCE_CONN_MODE	0x0020
 | 
					#define MGCP_MSG_PRESENCE_CONN_MODE	0x0020
 | 
				
			||||||
 | 
					#define MGCP_MSG_PRESENCE_X_OSMO_OSMUX_CID 0x4000
 | 
				
			||||||
/* See also RFC3435 section 3.2.1.3 */
 | 
					#define MGCP_MSG_PRESENCE_X_OSMO_IGN	0x8000
 | 
				
			||||||
#define MGCP_ENDPOINT_MAXLEN (255*2+1+1)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct mgcp_msg {
 | 
					struct mgcp_msg {
 | 
				
			||||||
	enum mgcp_verb verb;
 | 
						enum mgcp_verb verb;
 | 
				
			||||||
@@ -63,10 +115,20 @@ struct mgcp_msg {
 | 
				
			|||||||
	uint32_t presence;
 | 
						uint32_t presence;
 | 
				
			||||||
	char endpoint[MGCP_ENDPOINT_MAXLEN];
 | 
						char endpoint[MGCP_ENDPOINT_MAXLEN];
 | 
				
			||||||
	unsigned int call_id;
 | 
						unsigned int call_id;
 | 
				
			||||||
	uint32_t conn_id;
 | 
						char *conn_id;
 | 
				
			||||||
	uint16_t audio_port;
 | 
						uint16_t audio_port;
 | 
				
			||||||
	char *audio_ip;
 | 
						char *audio_ip;
 | 
				
			||||||
	enum mgcp_connection_mode conn_mode;
 | 
						enum mgcp_connection_mode conn_mode;
 | 
				
			||||||
 | 
						unsigned int ptime;
 | 
				
			||||||
 | 
						enum mgcp_codecs codecs[MGCP_MAX_CODECS];
 | 
				
			||||||
 | 
						unsigned int codecs_len;
 | 
				
			||||||
 | 
						struct ptmap ptmap[MGCP_MAX_CODECS];
 | 
				
			||||||
 | 
						unsigned int ptmap_len;
 | 
				
			||||||
 | 
						uint32_t x_osmo_ign;
 | 
				
			||||||
 | 
						bool x_osmo_osmux_use;
 | 
				
			||||||
 | 
						int x_osmo_osmux_cid; /* -1 is wildcard */
 | 
				
			||||||
 | 
						bool param_present;
 | 
				
			||||||
 | 
						struct mgcp_codec_param param;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void mgcp_client_conf_init(struct mgcp_client_conf *conf);
 | 
					void mgcp_client_conf_init(struct mgcp_client_conf *conf);
 | 
				
			||||||
@@ -77,13 +139,17 @@ struct mgcp_client_conf *mgcp_client_conf_actual(struct mgcp_client *mgcp);
 | 
				
			|||||||
struct mgcp_client *mgcp_client_init(void *ctx,
 | 
					struct mgcp_client *mgcp_client_init(void *ctx,
 | 
				
			||||||
				     struct mgcp_client_conf *conf);
 | 
									     struct mgcp_client_conf *conf);
 | 
				
			||||||
int mgcp_client_connect(struct mgcp_client *mgcp);
 | 
					int mgcp_client_connect(struct mgcp_client *mgcp);
 | 
				
			||||||
 | 
					int mgcp_client_connect2(struct mgcp_client *mgcp, unsigned int retry_n_ports);
 | 
				
			||||||
 | 
					void mgcp_client_disconnect(struct mgcp_client *mgcp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const char *mgcp_client_remote_addr_str(struct mgcp_client *mgcp);
 | 
					const char *mgcp_client_remote_addr_str(struct mgcp_client *mgcp);
 | 
				
			||||||
uint16_t mgcp_client_remote_port(struct mgcp_client *mgcp);
 | 
					uint16_t mgcp_client_remote_port(struct mgcp_client *mgcp);
 | 
				
			||||||
uint32_t mgcp_client_remote_addr_n(struct mgcp_client *mgcp);
 | 
					uint32_t mgcp_client_remote_addr_n(struct mgcp_client *mgcp) OSMO_DEPRECATED("deprecated, returns 0");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int mgcp_client_next_endpoint(struct mgcp_client *client);
 | 
					const char *mgcp_client_endpoint_domain(const struct mgcp_client *mgcp);
 | 
				
			||||||
void mgcp_client_release_endpoint(uint16_t id, struct mgcp_client *client);
 | 
					const char *mgcp_client_rtpbridge_wildcard(const struct mgcp_client *mgcp);
 | 
				
			||||||
 | 
					const char *mgcp_client_e1_epname(void *ctx, const struct mgcp_client *mgcp, uint8_t trunk_id, uint8_t ts,
 | 
				
			||||||
 | 
									  uint8_t rate, uint8_t offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Invoked when an MGCP response is received or sending failed.  When the
 | 
					/* Invoked when an MGCP response is received or sending failed.  When the
 | 
				
			||||||
 * response is passed as NULL, this indicates failure during transmission. */
 | 
					 * response is passed as NULL, this indicates failure during transmission. */
 | 
				
			||||||
@@ -92,27 +158,23 @@ int mgcp_response_parse_params(struct mgcp_response *r);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
int mgcp_client_tx(struct mgcp_client *mgcp, struct msgb *msg,
 | 
					int mgcp_client_tx(struct mgcp_client *mgcp, struct msgb *msg,
 | 
				
			||||||
		   mgcp_response_cb_t response_cb, void *priv);
 | 
							   mgcp_response_cb_t response_cb, void *priv);
 | 
				
			||||||
 | 
					int mgcp_client_cancel(struct mgcp_client *mgcp, mgcp_trans_id_t trans_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum mgcp_connection_mode;
 | 
					enum mgcp_connection_mode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct msgb *mgcp_msg_crcx(struct mgcp_client *mgcp,
 | 
					 | 
				
			||||||
			   uint16_t rtp_endpoint, unsigned int call_id,
 | 
					 | 
				
			||||||
			   enum mgcp_connection_mode mode)
 | 
					 | 
				
			||||||
OSMO_DEPRECATED("Use mgcp_msg_gen() instead");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct msgb *mgcp_msg_mdcx(struct mgcp_client *mgcp,
 | 
					 | 
				
			||||||
			   uint16_t rtp_endpoint, const char *rtp_conn_addr,
 | 
					 | 
				
			||||||
			   uint16_t rtp_port, enum mgcp_connection_mode mode)
 | 
					 | 
				
			||||||
OSMO_DEPRECATED("Use mgcp_msg_gen() instead");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct msgb *mgcp_msg_dlcx(struct mgcp_client *mgcp, uint16_t rtp_endpoint,
 | 
					 | 
				
			||||||
			   unsigned int call_id)
 | 
					 | 
				
			||||||
OSMO_DEPRECATED("Use mgcp_msg_gen() instead");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct msgb *mgcp_msg_gen(struct mgcp_client *mgcp, struct mgcp_msg *mgcp_msg);
 | 
					struct msgb *mgcp_msg_gen(struct mgcp_client *mgcp, struct mgcp_msg *mgcp_msg);
 | 
				
			||||||
 | 
					mgcp_trans_id_t mgcp_msg_trans_id(struct msgb *msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern const struct value_string mgcp_client_connection_mode_strs[];
 | 
					extern const struct value_string mgcp_client_connection_mode_strs[];
 | 
				
			||||||
static inline const char *mgcp_client_cmode_name(enum mgcp_connection_mode mode)
 | 
					static inline const char *mgcp_client_cmode_name(enum mgcp_connection_mode mode)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return get_value_string(mgcp_client_connection_mode_strs, mode);
 | 
						return get_value_string(mgcp_client_connection_mode_strs, mode);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum mgcp_codecs map_str_to_codec(const char *str);
 | 
				
			||||||
 | 
					unsigned int map_codec_to_pt(const struct ptmap *ptmap, unsigned int ptmap_len,
 | 
				
			||||||
 | 
								     enum mgcp_codecs codec);
 | 
				
			||||||
 | 
					enum mgcp_codecs map_pt_to_codec(struct ptmap *ptmap, unsigned int ptmap_len,
 | 
				
			||||||
 | 
									 unsigned int pt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *mgcp_client_name(const struct mgcp_client *mgcp);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										54
									
								
								include/osmocom/mgcp_client/mgcp_client_endpoint_fsm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								include/osmocom/mgcp_client/mgcp_client_endpoint_fsm.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
				
			|||||||
 | 
					/* FSM to manage multiple connections of an MGW endpoint */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/mgcp_client/mgcp_client_fsm.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LOG_MGCPC_EP(ep, level, fmt, args...) do { \
 | 
				
			||||||
 | 
						LOGPFSML(ep->fi, level, "%s " fmt, \
 | 
				
			||||||
 | 
							 osmo_mgcpc_ep_name(ep), ## args); \
 | 
				
			||||||
 | 
						} while(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_mgcpc_ep;
 | 
				
			||||||
 | 
					struct osmo_mgcpc_ep_ci;
 | 
				
			||||||
 | 
					struct osmo_tdef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_mgcpc_ep *osmo_mgcpc_ep_alloc(struct osmo_fsm_inst *parent, uint32_t parent_term_event,
 | 
				
			||||||
 | 
										  struct mgcp_client *mgcp_client,
 | 
				
			||||||
 | 
										  const struct osmo_tdef *T_defs,
 | 
				
			||||||
 | 
										  const char *fsm_id,
 | 
				
			||||||
 | 
										  const char *endpoint_str_fmt, ...);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_mgcpc_ep_ci *osmo_mgcpc_ep_ci_add(struct osmo_mgcpc_ep *ep, const char *label_fmt, ...);
 | 
				
			||||||
 | 
					const struct mgcp_conn_peer *osmo_mgcpc_ep_ci_get_rtp_info(const struct osmo_mgcpc_ep_ci *ci);
 | 
				
			||||||
 | 
					bool osmo_mgcpc_ep_ci_get_crcx_info_to_sockaddr(const struct osmo_mgcpc_ep_ci *ci, struct sockaddr_storage *dest);
 | 
				
			||||||
 | 
					bool osmo_mgcpc_ep_ci_get_crcx_info_to_osmux_cid(const struct osmo_mgcpc_ep_ci *ci, uint8_t* cid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct mgcp_conn_peer *osmo_mgcpc_ep_ci_get_remote_rtp_info(const struct osmo_mgcpc_ep_ci *ci);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void osmo_mgcpc_ep_ci_request(struct osmo_mgcpc_ep_ci *ci,
 | 
				
			||||||
 | 
								      enum mgcp_verb verb, const struct mgcp_conn_peer *verb_info,
 | 
				
			||||||
 | 
								      struct osmo_fsm_inst *notify,
 | 
				
			||||||
 | 
								      uint32_t event_success, uint32_t event_failure,
 | 
				
			||||||
 | 
								      void *notify_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void osmo_mgcpc_ep_cancel_notify(struct osmo_mgcpc_ep *ep, struct osmo_fsm_inst *notify);
 | 
				
			||||||
 | 
					struct osmo_mgcpc_ep *osmo_mgcpc_ep_ci_ep(struct osmo_mgcpc_ep_ci *ci);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! Dispatch a DLCX for the given connection.
 | 
				
			||||||
 | 
					 * \param ci  Connection identifier as obtained from osmo_mgcpc_ep_ci_add().
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline void osmo_mgcpc_ep_ci_dlcx(struct osmo_mgcpc_ep_ci *ci)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						osmo_mgcpc_ep_ci_request(ci, MGCP_VERB_DLCX, NULL, NULL, 0, 0, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void osmo_mgcpc_ep_clear(struct osmo_mgcpc_ep *ep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *osmo_mgcpc_ep_name(const struct osmo_mgcpc_ep *ep);
 | 
				
			||||||
 | 
					const char *osmo_mgcpc_ep_ci_name(const struct osmo_mgcpc_ep_ci *ci);
 | 
				
			||||||
 | 
					const char *osmo_mgcpc_ep_ci_id(const struct osmo_mgcpc_ep_ci *ci);
 | 
				
			||||||
 | 
					struct mgcp_client *osmo_mgcpc_ep_client(const struct osmo_mgcpc_ep *ep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern const struct value_string osmo_mgcp_verb_names[];
 | 
				
			||||||
 | 
					static inline const char *osmo_mgcp_verb_name(enum mgcp_verb val)
 | 
				
			||||||
 | 
					{ return get_value_string(osmo_mgcp_verb_names, val); }
 | 
				
			||||||
							
								
								
									
										74
									
								
								include/osmocom/mgcp_client/mgcp_client_fsm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								include/osmocom/mgcp_client/mgcp_client_fsm.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,74 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/mgcp_client/mgcp_common.h>
 | 
				
			||||||
 | 
					#include <osmocom/mgcp_client/mgcp_client.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/protocol/gsm_04_08.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! This struct organizes the connection infromation one connection side
 | 
				
			||||||
 | 
					 *  (either remote or local). It is used to pass parameters (local) to the FSM
 | 
				
			||||||
 | 
					 *  and get responses (remote) from the FSM as pointer attached to the FSM
 | 
				
			||||||
 | 
					 *  event.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  When modifiying a connection, the endpoint and call_id members may be left
 | 
				
			||||||
 | 
					 *  unpopulated. The call_id field is ignored in this case. If an endpoint
 | 
				
			||||||
 | 
					 *  identifier is supplied it is checked against the internal state to make
 | 
				
			||||||
 | 
					 *  sure it is correct. */
 | 
				
			||||||
 | 
					struct mgcp_conn_peer {
 | 
				
			||||||
 | 
						/*! RTP connection IP-Address (optional, string e.g. "127.0.0.1") */
 | 
				
			||||||
 | 
						char addr[INET6_ADDRSTRLEN];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! RTP connection IP-Port (optional)  */
 | 
				
			||||||
 | 
						uint16_t port;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! RTP endpoint */
 | 
				
			||||||
 | 
						char endpoint[MGCP_ENDPOINT_MAXLEN];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! CALL ID (unique per connection) */
 | 
				
			||||||
 | 
						unsigned int call_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! RTP packetization interval (optional) */
 | 
				
			||||||
 | 
						unsigned int ptime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! RTP codec list (optional) */
 | 
				
			||||||
 | 
						enum mgcp_codecs codecs[MGCP_MAX_CODECS];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! Number of codecs in RTP codec list (optional) */
 | 
				
			||||||
 | 
						unsigned int codecs_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! RTP payload type map (optional, only needed when payload types are
 | 
				
			||||||
 | 
						 * used that differ from what IANA/3GPP defines) */
 | 
				
			||||||
 | 
						struct ptmap ptmap[MGCP_MAX_CODECS];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! RTP payload type map length (optional, only needed when payload
 | 
				
			||||||
 | 
						 * types are used that differ from what IANA/3GPP defines) */
 | 
				
			||||||
 | 
						unsigned int ptmap_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! If nonzero, send 'X-Osmo-IGN:' header. This is useful e.g. for SCCPlite MSCs where the MSC is
 | 
				
			||||||
 | 
						 * known to issue incoherent or unknown CallIDs / to issue CRCX commands with a different domain
 | 
				
			||||||
 | 
						 * name than the BSC. An OsmoMGW will then ignore these and not fail on mismatches. */
 | 
				
			||||||
 | 
						uint32_t x_osmo_ign;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! send 'X-Osmux: %d' header (or "*" as wildcard). */
 | 
				
			||||||
 | 
						bool x_osmo_osmux_use;
 | 
				
			||||||
 | 
						/*! -1 means send wildcard. */
 | 
				
			||||||
 | 
						int x_osmo_osmux_cid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! If left MGCP_CONN_NONE, use MGCP_CONN_RECV_ONLY or MGCP_CONN_RECV_SEND, depending on whether an audio RTP
 | 
				
			||||||
 | 
						 * address is set. If != MGCP_CONN_NONE, force this conn mode. */
 | 
				
			||||||
 | 
						enum mgcp_connection_mode conn_mode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! If the codec requires additional format parameters (fmtp), those cann be set here, see also
 | 
				
			||||||
 | 
						 * mgcp_common.h */
 | 
				
			||||||
 | 
						bool param_present;
 | 
				
			||||||
 | 
						struct mgcp_codec_param param;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_fsm_inst *mgcp_conn_create(struct mgcp_client *mgcp, struct osmo_fsm_inst *parent_fi, uint32_t parent_term_evt,
 | 
				
			||||||
 | 
									       uint32_t parent_evt, struct mgcp_conn_peer *conn_peer);
 | 
				
			||||||
 | 
					int mgcp_conn_modify(struct osmo_fsm_inst *fi, uint32_t parent_evt, struct mgcp_conn_peer *conn_peer);
 | 
				
			||||||
 | 
					void mgcp_conn_delete(struct osmo_fsm_inst *fi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *mgcp_conn_get_ci(struct osmo_fsm_inst *fi);
 | 
				
			||||||
 | 
					struct mgcp_client *mgcp_conn_get_client(struct osmo_fsm_inst *fi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *osmo_mgcpc_conn_peer_name(const struct mgcp_conn_peer *info);
 | 
				
			||||||
@@ -4,13 +4,19 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define MSGB_CB_MGCP_TRANS_ID 0
 | 
					#define MSGB_CB_MGCP_TRANS_ID 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Struct that holds one endpoint name */
 | 
				
			||||||
 | 
					struct reset_ep {
 | 
				
			||||||
 | 
						struct llist_head list;
 | 
				
			||||||
 | 
						char name[MGCP_ENDPOINT_MAXLEN];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct mgcp_client {
 | 
					struct mgcp_client {
 | 
				
			||||||
	struct mgcp_client_conf actual;
 | 
						struct mgcp_client_conf actual;
 | 
				
			||||||
	uint32_t remote_addr;
 | 
					 | 
				
			||||||
	struct osmo_wqueue wq;
 | 
						struct osmo_wqueue wq;
 | 
				
			||||||
	mgcp_trans_id_t next_trans_id;
 | 
						mgcp_trans_id_t next_trans_id;
 | 
				
			||||||
	struct llist_head responses_pending;
 | 
						struct llist_head responses_pending;
 | 
				
			||||||
	struct llist_head inuse_endpoints;
 | 
						struct llist_head inuse_endpoints;
 | 
				
			||||||
 | 
						struct mgcp_client_pool *pool;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct mgcp_inuse_endpoint {
 | 
					struct mgcp_inuse_endpoint {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										11
									
								
								include/osmocom/mgcp_client/mgcp_client_pool.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								include/osmocom/mgcp_client/mgcp_client_pool.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct mgcp_client;
 | 
				
			||||||
 | 
					struct mgcp_client_pool;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct mgcp_client_pool *mgcp_client_pool_alloc(void *talloc_ctx);
 | 
				
			||||||
 | 
					void mgcp_client_pool_vty_init(int parent_node, int mgw_node, const char *indent, struct mgcp_client_pool *pool);
 | 
				
			||||||
 | 
					unsigned int mgcp_client_pool_connect(struct mgcp_client_pool *pool);
 | 
				
			||||||
 | 
					void mgcp_client_pool_register_single(struct mgcp_client_pool *pool, struct mgcp_client *mgcp_client);
 | 
				
			||||||
 | 
					struct mgcp_client *mgcp_client_pool_get(struct mgcp_client_pool *pool);
 | 
				
			||||||
 | 
					void mgcp_client_pool_put(struct mgcp_client *mgcp_client);
 | 
				
			||||||
							
								
								
									
										45
									
								
								include/osmocom/mgcp_client/mgcp_client_pool_internal.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								include/osmocom/mgcp_client/mgcp_client_pool_internal.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Struct to handle a member of a pool of MGWs. */
 | 
				
			||||||
 | 
					struct mgcp_client_pool_member {
 | 
				
			||||||
 | 
						struct llist_head list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Reference number assinged by VTY. This number is used to manage the pool from the VTY and to identify it in
 | 
				
			||||||
 | 
						 * the log. */
 | 
				
			||||||
 | 
						unsigned int nr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* MGCP client configuration, this is not the running configuration, when mgcp_client_init() is executed, a
 | 
				
			||||||
 | 
						 * copy of this config is created. */
 | 
				
			||||||
 | 
						struct mgcp_client_conf conf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* MGCP client descriptor, will be automatically allocated when mgcp_client_pool_connect() is called. (the MGCP
 | 
				
			||||||
 | 
						 * client is connected when this pointer is populated) */
 | 
				
			||||||
 | 
						struct mgcp_client *client;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* A pool member may be set as 'blocked' from the VTY, this means that the pool member may still work and serve
 | 
				
			||||||
 | 
						 * ongoing calls, but it won't be picked from the pool anymore. */
 | 
				
			||||||
 | 
						bool blocked;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Reference counter to count how often this pool member is currently picked. */
 | 
				
			||||||
 | 
						unsigned int refcount;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Struct to handle a pool of MGWs. (Use _pool functions) */
 | 
				
			||||||
 | 
					struct mgcp_client_pool {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* A pointer to a 'single' mgcp client. This is a non-pooled MGCP client that is configured using
 | 
				
			||||||
 | 
						 * mgcp_client_vty_init() and actively registered by the API user using mgcp_client_pool_register_single() */
 | 
				
			||||||
 | 
						struct mgcp_client *mgcp_client_single;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* A list that manages the pool members (see above) */
 | 
				
			||||||
 | 
						struct llist_head pool;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* String to use for indentation when writing the configuration file to the VTY. This field is populated by
 | 
				
			||||||
 | 
						 * mgcp_client_pool_vty_init() */
 | 
				
			||||||
 | 
						char *vty_indent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* VTY node specification used with this pool. This field is populated by mgcp_client_pool_vty_init() */
 | 
				
			||||||
 | 
						struct cmd_node *vty_node;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *mgcp_client_pool_member_name(const struct mgcp_client_pool_member *pool_member);
 | 
				
			||||||
@@ -1,10 +0,0 @@
 | 
				
			|||||||
prefix=@prefix@
 | 
					 | 
				
			||||||
exec_prefix=@exec_prefix@
 | 
					 | 
				
			||||||
libdir=@libdir@
 | 
					 | 
				
			||||||
includedir=@includedir@
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Name: Osmocom legacy Media Gateway Control Protocol library
 | 
					 | 
				
			||||||
Description: C Utility Library
 | 
					 | 
				
			||||||
Version: @VERSION@
 | 
					 | 
				
			||||||
Libs: -L${libdir} -losmo-legacy-mgcp
 | 
					 | 
				
			||||||
Cflags: -I${includedir}/
 | 
					 | 
				
			||||||
@@ -1,10 +0,0 @@
 | 
				
			|||||||
prefix=@prefix@
 | 
					 | 
				
			||||||
exec_prefix=@exec_prefix@
 | 
					 | 
				
			||||||
libdir=@libdir@
 | 
					 | 
				
			||||||
includedir=@includedir@
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Name: Osmocom Media Gateway Control Protocol library
 | 
					 | 
				
			||||||
Description: C Utility Library
 | 
					 | 
				
			||||||
Version: @VERSION@
 | 
					 | 
				
			||||||
Libs: -L${libdir} -losmo-mgcp
 | 
					 | 
				
			||||||
Cflags: -I${includedir}/
 | 
					 | 
				
			||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
#!/usr/bin/env python
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# (C) 2013 by Katerina Barone-Adesi <kat.obsc@gmail.com>
 | 
					# (C) 2013 by Katerina Barone-Adesi <kat.obsc@gmail.com>
 | 
				
			||||||
# This program is free software: you can redistribute it and/or modify
 | 
					# This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
@@ -17,11 +17,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
app_configs = {
 | 
					app_configs = {
 | 
				
			||||||
    "osmo-mgw": ["doc/examples/osmo-mgw/osmo-mgw.cfg"],
 | 
					    "osmo-mgw": ["doc/examples/osmo-mgw/osmo-mgw.cfg"],
 | 
				
			||||||
    "osmo-bsc_mgcp": ["doc/examples/osmo-bsc_mgcp/mgcp.cfg"],
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
apps = [(4243, "src/osmo-mgw/osmo-mgw", "OsmoMGW", "osmo-mgw"),
 | 
					apps = [(4243, "src/osmo-mgw/osmo-mgw", "OsmoMGW", "osmo-mgw"),
 | 
				
			||||||
        (4243, "src/osmo-bsc_mgcp/osmo-bsc_mgcp", "OpenBSC MGCP", "osmo-bsc_mgcp"),
 | 
					 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
vty_command = ["./src/osmo-mgw/osmo-mgw", "-c",
 | 
					vty_command = ["./src/osmo-mgw/osmo-mgw", "-c",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,13 +21,11 @@ AM_LDFLAGS = \
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# Libraries
 | 
					# Libraries
 | 
				
			||||||
SUBDIRS = \
 | 
					SUBDIRS = \
 | 
				
			||||||
	libosmo-legacy-mgcp \
 | 
					 | 
				
			||||||
	libosmo-mgcp-client \
 | 
						libosmo-mgcp-client \
 | 
				
			||||||
	libosmo-mgcp \
 | 
						libosmo-mgcp \
 | 
				
			||||||
	$(NULL)
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Programs
 | 
					# Programs
 | 
				
			||||||
SUBDIRS += \
 | 
					SUBDIRS += \
 | 
				
			||||||
	osmo-bsc_mgcp \
 | 
					 | 
				
			||||||
	osmo-mgw \
 | 
						osmo-mgw \
 | 
				
			||||||
	$(NULL)
 | 
						$(NULL)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,51 +0,0 @@
 | 
				
			|||||||
AM_CPPFLAGS = \
 | 
					 | 
				
			||||||
	$(all_includes) \
 | 
					 | 
				
			||||||
	-I$(top_srcdir)/include \
 | 
					 | 
				
			||||||
	-I$(top_builddir) \
 | 
					 | 
				
			||||||
	$(NULL)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
AM_CFLAGS = \
 | 
					 | 
				
			||||||
	-Wall \
 | 
					 | 
				
			||||||
	$(LIBOSMOCORE_CFLAGS) \
 | 
					 | 
				
			||||||
	$(LIBOSMOVTY_CFLAGS) \
 | 
					 | 
				
			||||||
	$(LIBOSMONETIF_CFLAGS) \
 | 
					 | 
				
			||||||
	$(COVERAGE_CFLAGS) \
 | 
					 | 
				
			||||||
	$(LIBBCG729_CFLAGS) \
 | 
					 | 
				
			||||||
	$(NULL)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
AM_LDFLAGS = \
 | 
					 | 
				
			||||||
	$(LIBOSMOCORE_LIBS) \
 | 
					 | 
				
			||||||
	$(LIBOSMOVTY_LIBS) \
 | 
					 | 
				
			||||||
	$(LIBOSMONETIF_LIBS) \
 | 
					 | 
				
			||||||
	$(COVERAGE_LDFLAGS) \
 | 
					 | 
				
			||||||
	$(LIBBCG729_LIBS) \
 | 
					 | 
				
			||||||
	$(LIBRARY_GSM) \
 | 
					 | 
				
			||||||
	$(NULL)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# This is not at all related to the release version, but a range of supported
 | 
					 | 
				
			||||||
# API versions. Read TODO_RELEASE in the source tree's root!
 | 
					 | 
				
			||||||
LEGACY_MGCP_LIBVERSION=0:0:0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
lib_LTLIBRARIES = \
 | 
					 | 
				
			||||||
	libosmo-legacy-mgcp.la \
 | 
					 | 
				
			||||||
	$(NULL)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
noinst_HEADERS = \
 | 
					 | 
				
			||||||
	g711common.h \
 | 
					 | 
				
			||||||
	$(NULL)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
libosmo_legacy_mgcp_la_SOURCES = \
 | 
					 | 
				
			||||||
	mgcp_common.c \
 | 
					 | 
				
			||||||
	mgcp_protocol.c \
 | 
					 | 
				
			||||||
	mgcp_network.c \
 | 
					 | 
				
			||||||
	mgcp_vty.c \
 | 
					 | 
				
			||||||
	mgcp_osmux.c \
 | 
					 | 
				
			||||||
	mgcp_sdp.c \
 | 
					 | 
				
			||||||
	$(NULL)
 | 
					 | 
				
			||||||
if BUILD_MGCP_TRANSCODING
 | 
					 | 
				
			||||||
libosmo_legacy_mgcp_la_SOURCES += \
 | 
					 | 
				
			||||||
	mgcp_transcode.c \
 | 
					 | 
				
			||||||
	$(NULL)
 | 
					 | 
				
			||||||
endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
libosmo_legacy_mgcp_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(LEGACY_MGCP_LIBVERSION)
 | 
					 | 
				
			||||||
@@ -1,187 +0,0 @@
 | 
				
			|||||||
/*
 | 
					 | 
				
			||||||
 *  PCM - A-Law conversion
 | 
					 | 
				
			||||||
 *  Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *  Wrapper for linphone Codec class by Simon Morlat <simon.morlat@linphone.org>
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *  This program is free software; you can redistribute it and/or modify
 | 
					 | 
				
			||||||
 *  it under the terms of the GNU General Public License as published by
 | 
					 | 
				
			||||||
 *  the Free Software Foundation; either version 2 of the License, or
 | 
					 | 
				
			||||||
 *  (at your option) any later version.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *  This program is distributed in the hope that it will be useful,
 | 
					 | 
				
			||||||
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 | 
				
			||||||
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					 | 
				
			||||||
 *  GNU General Public License for more details.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *  You should have received a copy of the GNU General Public License
 | 
					 | 
				
			||||||
 *  along with this program; if not, write to the Free Software
 | 
					 | 
				
			||||||
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline int val_seg(int val)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int r = 0;
 | 
					 | 
				
			||||||
	val >>= 7; /*7 = 4 + 3*/
 | 
					 | 
				
			||||||
	if (val & 0xf0) {
 | 
					 | 
				
			||||||
		val >>= 4;
 | 
					 | 
				
			||||||
		r += 4;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (val & 0x0c) {
 | 
					 | 
				
			||||||
		val >>= 2;
 | 
					 | 
				
			||||||
		r += 2;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (val & 0x02)
 | 
					 | 
				
			||||||
		r += 1;
 | 
					 | 
				
			||||||
	return r;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * s16_to_alaw() - Convert a 16-bit linear PCM value to 8-bit A-law
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * s16_to_alaw() accepts an 16-bit integer and encodes it as A-law data.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *		Linear Input Code	Compressed Code
 | 
					 | 
				
			||||||
 *	------------------------	---------------
 | 
					 | 
				
			||||||
 *	0000000wxyza			000wxyz
 | 
					 | 
				
			||||||
 *	0000001wxyza			001wxyz
 | 
					 | 
				
			||||||
 *	000001wxyzab			010wxyz
 | 
					 | 
				
			||||||
 *	00001wxyzabc			011wxyz
 | 
					 | 
				
			||||||
 *	0001wxyzabcd			100wxyz
 | 
					 | 
				
			||||||
 *	001wxyzabcde			101wxyz
 | 
					 | 
				
			||||||
 *	01wxyzabcdef			110wxyz
 | 
					 | 
				
			||||||
 *	1wxyzabcdefg			111wxyz
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * For further information see John C. Bellamy's Digital Telephony, 1982,
 | 
					 | 
				
			||||||
 * John Wiley & Sons, pps 98-111 and 472-476.
 | 
					 | 
				
			||||||
 * G711 is designed for 13 bits input signal, this function add extra shifting to take this into account.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline unsigned char s16_to_alaw(int pcm_val)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int		mask;
 | 
					 | 
				
			||||||
	int		seg;
 | 
					 | 
				
			||||||
	unsigned char	aval;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (pcm_val >= 0) {
 | 
					 | 
				
			||||||
		mask = 0xD5;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		mask = 0x55;
 | 
					 | 
				
			||||||
		pcm_val = -pcm_val;
 | 
					 | 
				
			||||||
		if (pcm_val > 0x7fff)
 | 
					 | 
				
			||||||
			pcm_val = 0x7fff;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (pcm_val < 256) /*256 = 32 << 3*/
 | 
					 | 
				
			||||||
		aval = pcm_val >> 4; /*4 = 1 + 3*/
 | 
					 | 
				
			||||||
	else {
 | 
					 | 
				
			||||||
		/* Convert the scaled magnitude to segment number. */
 | 
					 | 
				
			||||||
		seg = val_seg(pcm_val);
 | 
					 | 
				
			||||||
		aval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0x0f);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return aval ^ mask;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * alaw_to_s16() - Convert an A-law value to 16-bit linear PCM
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static inline int alaw_to_s16(unsigned char a_val)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int		t;
 | 
					 | 
				
			||||||
	int		seg;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	a_val ^= 0x55;
 | 
					 | 
				
			||||||
	t = a_val & 0x7f;
 | 
					 | 
				
			||||||
	if (t < 16)
 | 
					 | 
				
			||||||
		t = (t << 4) + 8;
 | 
					 | 
				
			||||||
	else {
 | 
					 | 
				
			||||||
		seg = (t >> 4) & 0x07;
 | 
					 | 
				
			||||||
		t = ((t & 0x0f) << 4) + 0x108;
 | 
					 | 
				
			||||||
		t <<= seg -1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return ((a_val & 0x80) ? t : -t);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * s16_to_ulaw() - Convert a linear PCM value to u-law
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * In order to simplify the encoding process, the original linear magnitude
 | 
					 | 
				
			||||||
 * is biased by adding 33 which shifts the encoding range from (0 - 8158) to
 | 
					 | 
				
			||||||
 * (33 - 8191). The result can be seen in the following encoding table:
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *	Biased Linear Input Code	Compressed Code
 | 
					 | 
				
			||||||
 *	------------------------	---------------
 | 
					 | 
				
			||||||
 *	00000001wxyza			000wxyz
 | 
					 | 
				
			||||||
 *	0000001wxyzab			001wxyz
 | 
					 | 
				
			||||||
 *	000001wxyzabc			010wxyz
 | 
					 | 
				
			||||||
 *	00001wxyzabcd			011wxyz
 | 
					 | 
				
			||||||
 *	0001wxyzabcde			100wxyz
 | 
					 | 
				
			||||||
 *	001wxyzabcdef			101wxyz
 | 
					 | 
				
			||||||
 *	01wxyzabcdefg			110wxyz
 | 
					 | 
				
			||||||
 *	1wxyzabcdefgh			111wxyz
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Each biased linear code has a leading 1 which identifies the segment
 | 
					 | 
				
			||||||
 * number. The value of the segment number is equal to 7 minus the number
 | 
					 | 
				
			||||||
 * of leading 0's. The quantization interval is directly available as the
 | 
					 | 
				
			||||||
 * four bits wxyz.  * The trailing bits (a - h) are ignored.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Ordinarily the complement of the resulting code word is used for
 | 
					 | 
				
			||||||
 * transmission, and so the code word is complemented before it is returned.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * For further information see John C. Bellamy's Digital Telephony, 1982,
 | 
					 | 
				
			||||||
 * John Wiley & Sons, pps 98-111 and 472-476.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline unsigned char s16_to_ulaw(int pcm_val)	/* 2's complement (16-bit range) */
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int mask;
 | 
					 | 
				
			||||||
	int seg;
 | 
					 | 
				
			||||||
	unsigned char uval;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (pcm_val < 0) {
 | 
					 | 
				
			||||||
		pcm_val = 0x84 - pcm_val;
 | 
					 | 
				
			||||||
		mask = 0x7f;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		pcm_val += 0x84;
 | 
					 | 
				
			||||||
		mask = 0xff;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (pcm_val > 0x7fff)
 | 
					 | 
				
			||||||
		pcm_val = 0x7fff;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Convert the scaled magnitude to segment number. */
 | 
					 | 
				
			||||||
	seg = val_seg(pcm_val);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * Combine the sign, segment, quantization bits;
 | 
					 | 
				
			||||||
	 * and complement the code word.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	uval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0x0f);
 | 
					 | 
				
			||||||
	return uval ^ mask;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * ulaw_to_s16() - Convert a u-law value to 16-bit linear PCM
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * First, a biased linear code is derived from the code word. An unbiased
 | 
					 | 
				
			||||||
 * output can then be obtained by subtracting 33 from the biased code.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Note that this function expects to be passed the complement of the
 | 
					 | 
				
			||||||
 * original code word. This is in keeping with ISDN conventions.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static inline int ulaw_to_s16(unsigned char u_val)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int t;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Complement to obtain normal u-law value. */
 | 
					 | 
				
			||||||
	u_val = ~u_val;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * Extract and bias the quantization bits. Then
 | 
					 | 
				
			||||||
	 * shift up by the segment number and subtract out the bias.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	t = ((u_val & 0x0f) << 3) + 0x84;
 | 
					 | 
				
			||||||
	t <<= (u_val & 0x70) >> 4;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return ((u_val & 0x80) ? (0x84 - t) : (t - 0x84));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,54 +0,0 @@
 | 
				
			|||||||
/* Media Gateway Control Protocol Media Gateway: RFC 3435 */
 | 
					 | 
				
			||||||
/* Implementations useful both for the MGCP GW as well as MGCP GW clients */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * (C) 2016 by sysmocom s.m.f.c. GmbH <info@sysmocom.de>
 | 
					 | 
				
			||||||
 * All Rights Reserved
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is free software; you can redistribute it and/or modify
 | 
					 | 
				
			||||||
 * it under the terms of the GNU Affero General Public License as published by
 | 
					 | 
				
			||||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
					 | 
				
			||||||
 * (at your option) any later version.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is distributed in the hope that it will be useful,
 | 
					 | 
				
			||||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 | 
				
			||||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					 | 
				
			||||||
 * GNU Affero General Public License for more details.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * You should have received a copy of the GNU Affero General Public License
 | 
					 | 
				
			||||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <errno.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <osmocom/core/utils.h>
 | 
					 | 
				
			||||||
#include <osmocom/legacy_mgcp/mgcp.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const struct value_string mgcp_connection_mode_strs[] = {
 | 
					 | 
				
			||||||
	{ MGCP_CONN_NONE, "none" },
 | 
					 | 
				
			||||||
	{ MGCP_CONN_RECV_SEND, "sendrecv" },
 | 
					 | 
				
			||||||
	{ MGCP_CONN_SEND_ONLY, "sendonly" },
 | 
					 | 
				
			||||||
	{ MGCP_CONN_RECV_ONLY, "recvonly" },
 | 
					 | 
				
			||||||
	{ MGCP_CONN_LOOPBACK, "loopback" },
 | 
					 | 
				
			||||||
	{ 0, NULL }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Ensure that the msg->l2h is NUL terminated. */
 | 
					 | 
				
			||||||
int mgcp_msg_terminate_nul(struct msgb *msg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	unsigned char *tail = msg->l2h + msgb_l2len(msg); /* char after l2 data */
 | 
					 | 
				
			||||||
	if (tail[-1] == '\0')
 | 
					 | 
				
			||||||
		/* nothing to do */;
 | 
					 | 
				
			||||||
	else if (msgb_tailroom(msg) > 0)
 | 
					 | 
				
			||||||
		tail[0] = '\0';
 | 
					 | 
				
			||||||
	else if (tail[-1] == '\r' || tail[-1] == '\n')
 | 
					 | 
				
			||||||
		tail[-1] = '\0';
 | 
					 | 
				
			||||||
	else {
 | 
					 | 
				
			||||||
		LOGP(DLMGCP, LOGL_ERROR, "Cannot NUL terminate MGCP message: "
 | 
					 | 
				
			||||||
		     "Length: %d, Buffer size: %d\n",
 | 
					 | 
				
			||||||
		     msgb_l2len(msg), msg->data_len);
 | 
					 | 
				
			||||||
		return -ENOTSUP;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,583 +0,0 @@
 | 
				
			|||||||
/*
 | 
					 | 
				
			||||||
 * (C) 2012-2013 by Pablo Neira Ayuso <pablo@gnumonks.org>
 | 
					 | 
				
			||||||
 * (C) 2012-2013 by On Waves ehf <http://www.on-waves.com>
 | 
					 | 
				
			||||||
 * All rights not specifically granted under this license are reserved.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is free software; you can redistribute it and/or modify it
 | 
					 | 
				
			||||||
 * under the terms of the GNU Affero General Public License as published by the
 | 
					 | 
				
			||||||
 * Free Software Foundation; either version 3 of the License, or (at your
 | 
					 | 
				
			||||||
 * option) any later version.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <stdio.h> /* for printf */
 | 
					 | 
				
			||||||
#include <string.h> /* for memcpy */
 | 
					 | 
				
			||||||
#include <stdlib.h> /* for abs */
 | 
					 | 
				
			||||||
#include <inttypes.h> /* for PRIu64 */
 | 
					 | 
				
			||||||
#include <netinet/in.h>
 | 
					 | 
				
			||||||
#include <osmocom/core/msgb.h>
 | 
					 | 
				
			||||||
#include <osmocom/core/talloc.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <osmocom/netif/osmux.h>
 | 
					 | 
				
			||||||
#include <osmocom/netif/rtp.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <osmocom/legacy_mgcp/mgcp.h>
 | 
					 | 
				
			||||||
#include <osmocom/legacy_mgcp/mgcp_internal.h>
 | 
					 | 
				
			||||||
#include <osmocom/legacy_mgcp/osmux.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct osmo_fd osmux_fd;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static LLIST_HEAD(osmux_handle_list);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct osmux_handle {
 | 
					 | 
				
			||||||
	struct llist_head head;
 | 
					 | 
				
			||||||
	struct osmux_in_handle *in;
 | 
					 | 
				
			||||||
	struct in_addr rem_addr;
 | 
					 | 
				
			||||||
	int rem_port;
 | 
					 | 
				
			||||||
	int refcnt;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void *osmux;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void osmux_deliver(struct msgb *batch_msg, void *data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct osmux_handle *handle = data;
 | 
					 | 
				
			||||||
	struct sockaddr_in out = {
 | 
					 | 
				
			||||||
		.sin_family = AF_INET,
 | 
					 | 
				
			||||||
		.sin_port = handle->rem_port,
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	memcpy(&out.sin_addr, &handle->rem_addr, sizeof(handle->rem_addr));
 | 
					 | 
				
			||||||
	sendto(osmux_fd.fd, batch_msg->data, batch_msg->len, 0,
 | 
					 | 
				
			||||||
		(struct sockaddr *)&out, sizeof(out));
 | 
					 | 
				
			||||||
	msgb_free(batch_msg);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct osmux_handle *
 | 
					 | 
				
			||||||
osmux_handle_find_get(struct in_addr *addr, int rem_port)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct osmux_handle *h;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Lookup for existing OSMUX handle for this destination address. */
 | 
					 | 
				
			||||||
	llist_for_each_entry(h, &osmux_handle_list, head) {
 | 
					 | 
				
			||||||
		if (memcmp(&h->rem_addr, addr, sizeof(struct in_addr)) == 0 &&
 | 
					 | 
				
			||||||
		    h->rem_port == rem_port) {
 | 
					 | 
				
			||||||
			LOGP(DLMGCP, LOGL_DEBUG, "using existing OSMUX handle "
 | 
					 | 
				
			||||||
						"for addr=%s:%d\n",
 | 
					 | 
				
			||||||
				inet_ntoa(*addr), ntohs(rem_port));
 | 
					 | 
				
			||||||
			h->refcnt++;
 | 
					 | 
				
			||||||
			return h;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return NULL;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void osmux_handle_put(struct osmux_in_handle *in)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct osmux_handle *h;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Lookup for existing OSMUX handle for this destination address. */
 | 
					 | 
				
			||||||
	llist_for_each_entry(h, &osmux_handle_list, head) {
 | 
					 | 
				
			||||||
		if (h->in == in) {
 | 
					 | 
				
			||||||
			if (--h->refcnt == 0) {
 | 
					 | 
				
			||||||
				LOGP(DLMGCP, LOGL_INFO,
 | 
					 | 
				
			||||||
				     "Releasing unused osmux handle for %s:%d\n",
 | 
					 | 
				
			||||||
				     inet_ntoa(h->rem_addr),
 | 
					 | 
				
			||||||
				     ntohs(h->rem_port));
 | 
					 | 
				
			||||||
				LOGP(DLMGCP, LOGL_INFO, "Stats: "
 | 
					 | 
				
			||||||
				     "input RTP msgs: %u bytes: %"PRIu64" "
 | 
					 | 
				
			||||||
				     "output osmux msgs: %u bytes: %"PRIu64"\n",
 | 
					 | 
				
			||||||
				     in->stats.input_rtp_msgs,
 | 
					 | 
				
			||||||
				     in->stats.input_rtp_bytes,
 | 
					 | 
				
			||||||
				     in->stats.output_osmux_msgs,
 | 
					 | 
				
			||||||
				     in->stats.output_osmux_bytes);
 | 
					 | 
				
			||||||
				llist_del(&h->head);
 | 
					 | 
				
			||||||
				osmux_xfrm_input_fini(h->in);
 | 
					 | 
				
			||||||
				talloc_free(h);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	LOGP(DLMGCP, LOGL_ERROR, "cannot find Osmux input handle %p\n", in);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct osmux_handle *
 | 
					 | 
				
			||||||
osmux_handle_alloc(struct mgcp_config *cfg, struct in_addr *addr, int rem_port)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct osmux_handle *h;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	h = talloc_zero(osmux, struct osmux_handle);
 | 
					 | 
				
			||||||
	if (!h)
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
	h->rem_addr = *addr;
 | 
					 | 
				
			||||||
	h->rem_port = rem_port;
 | 
					 | 
				
			||||||
	h->refcnt++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	h->in = talloc_zero(h, struct osmux_in_handle);
 | 
					 | 
				
			||||||
	if (!h->in) {
 | 
					 | 
				
			||||||
		talloc_free(h);
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	h->in->osmux_seq = 0; /* sequence number to start OSmux message from */
 | 
					 | 
				
			||||||
	h->in->batch_factor = cfg->osmux_batch;
 | 
					 | 
				
			||||||
	/* If batch size is zero, the library defaults to 1470 bytes. */
 | 
					 | 
				
			||||||
	h->in->batch_size = cfg->osmux_batch_size;
 | 
					 | 
				
			||||||
	h->in->deliver = osmux_deliver;
 | 
					 | 
				
			||||||
	osmux_xfrm_input_init(h->in);
 | 
					 | 
				
			||||||
	h->in->data = h;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	llist_add(&h->head, &osmux_handle_list);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	LOGP(DLMGCP, LOGL_DEBUG, "created new OSMUX handle for addr=%s:%d\n",
 | 
					 | 
				
			||||||
		inet_ntoa(*addr), ntohs(rem_port));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return h;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct osmux_in_handle *
 | 
					 | 
				
			||||||
osmux_handle_lookup(struct mgcp_config *cfg, struct in_addr *addr, int rem_port)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct osmux_handle *h;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	h = osmux_handle_find_get(addr, rem_port);
 | 
					 | 
				
			||||||
	if (h != NULL)
 | 
					 | 
				
			||||||
		return h->in;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	h = osmux_handle_alloc(cfg, addr, rem_port);
 | 
					 | 
				
			||||||
	if (h == NULL)
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return h->in;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int osmux_xfrm_to_osmux(int type, char *buf, int rc, struct mgcp_endpoint *endp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
	struct msgb *msg;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	msg = msgb_alloc(4096, "RTP");
 | 
					 | 
				
			||||||
	if (!msg)
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	memcpy(msg->data, buf, rc);
 | 
					 | 
				
			||||||
	msgb_put(msg, rc);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	while ((ret = osmux_xfrm_input(endp->osmux.in, msg, endp->osmux.cid)) > 0) {
 | 
					 | 
				
			||||||
		/* batch full, build and deliver it */
 | 
					 | 
				
			||||||
		osmux_xfrm_input_deliver(endp->osmux.in);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct mgcp_endpoint *
 | 
					 | 
				
			||||||
endpoint_lookup(struct mgcp_config *cfg, int cid,
 | 
					 | 
				
			||||||
		struct in_addr *from_addr, int type)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct mgcp_endpoint *tmp = NULL;
 | 
					 | 
				
			||||||
	int i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Lookup for the endpoint that corresponds to this port */
 | 
					 | 
				
			||||||
	for (i=0; i<cfg->trunk.number_endpoints; i++) {
 | 
					 | 
				
			||||||
		struct in_addr *this;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		tmp = &cfg->trunk.endpoints[i];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (!tmp->allocated)
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		switch(type) {
 | 
					 | 
				
			||||||
		case MGCP_DEST_NET:
 | 
					 | 
				
			||||||
			this = &tmp->net_end.addr;
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case MGCP_DEST_BTS:
 | 
					 | 
				
			||||||
			this = &tmp->bts_end.addr;
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			/* Should not ever happen */
 | 
					 | 
				
			||||||
			LOGP(DLMGCP, LOGL_ERROR, "Bad type %d. Fix your code.\n", type);
 | 
					 | 
				
			||||||
			return NULL;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (tmp->osmux.cid == cid && this->s_addr == from_addr->s_addr)
 | 
					 | 
				
			||||||
			return tmp;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	LOGP(DLMGCP, LOGL_ERROR, "Cannot find endpoint with cid=%d\n", cid);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return NULL;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void scheduled_tx_net_cb(struct msgb *msg, void *data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct mgcp_endpoint *endp = data;
 | 
					 | 
				
			||||||
	struct sockaddr_in addr = {
 | 
					 | 
				
			||||||
		.sin_addr = endp->net_end.addr,
 | 
					 | 
				
			||||||
		.sin_port = endp->net_end.rtp_port,
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	endp->bts_end.octets += msg->len;
 | 
					 | 
				
			||||||
	endp->bts_end.packets++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	mgcp_send(endp, MGCP_DEST_NET, 1, &addr, (char *)msg->data, msg->len);
 | 
					 | 
				
			||||||
	msgb_free(msg);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void scheduled_tx_bts_cb(struct msgb *msg, void *data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct mgcp_endpoint *endp = data;
 | 
					 | 
				
			||||||
	struct sockaddr_in addr = {
 | 
					 | 
				
			||||||
		.sin_addr = endp->bts_end.addr,
 | 
					 | 
				
			||||||
		.sin_port = endp->bts_end.rtp_port,
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	endp->net_end.octets += msg->len;
 | 
					 | 
				
			||||||
	endp->net_end.packets++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	mgcp_send(endp, MGCP_DEST_BTS, 1, &addr, (char *)msg->data, msg->len);
 | 
					 | 
				
			||||||
	msgb_free(msg);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct msgb *osmux_recv(struct osmo_fd *ofd, struct sockaddr_in *addr)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct msgb *msg;
 | 
					 | 
				
			||||||
	socklen_t slen = sizeof(*addr);
 | 
					 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	msg = msgb_alloc(4096, "OSMUX");
 | 
					 | 
				
			||||||
	if (!msg) {
 | 
					 | 
				
			||||||
		LOGP(DLMGCP, LOGL_ERROR, "cannot allocate message\n");
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	ret = recvfrom(ofd->fd, msg->data, msg->data_len, 0,
 | 
					 | 
				
			||||||
			(struct sockaddr *)addr, &slen);
 | 
					 | 
				
			||||||
	if (ret <= 0) {
 | 
					 | 
				
			||||||
		msgb_free(msg);
 | 
					 | 
				
			||||||
		LOGP(DLMGCP, LOGL_ERROR, "cannot receive message\n");
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	msgb_put(msg, ret);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return msg;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define osmux_chunk_length(msg, rem) (rem - msg->len);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int osmux_read_from_bsc_nat_cb(struct osmo_fd *ofd, unsigned int what)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct msgb *msg;
 | 
					 | 
				
			||||||
	struct osmux_hdr *osmuxh;
 | 
					 | 
				
			||||||
	struct llist_head list;
 | 
					 | 
				
			||||||
	struct sockaddr_in addr;
 | 
					 | 
				
			||||||
	struct mgcp_config *cfg = ofd->data;
 | 
					 | 
				
			||||||
	uint32_t rem;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	msg = osmux_recv(ofd, &addr);
 | 
					 | 
				
			||||||
	if (!msg)
 | 
					 | 
				
			||||||
		return -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* not any further processing dummy messages */
 | 
					 | 
				
			||||||
	if (msg->data[0] == MGCP_DUMMY_LOAD)
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	rem = msg->len;
 | 
					 | 
				
			||||||
	while((osmuxh = osmux_xfrm_output_pull(msg)) != NULL) {
 | 
					 | 
				
			||||||
		struct mgcp_endpoint *endp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* Yes, we use MGCP_DEST_NET to locate the origin */
 | 
					 | 
				
			||||||
		endp = endpoint_lookup(cfg, osmuxh->circuit_id,
 | 
					 | 
				
			||||||
				       &addr.sin_addr, MGCP_DEST_NET);
 | 
					 | 
				
			||||||
		if (!endp) {
 | 
					 | 
				
			||||||
			LOGP(DLMGCP, LOGL_ERROR,
 | 
					 | 
				
			||||||
			     "Cannot find an endpoint for circuit_id=%d\n",
 | 
					 | 
				
			||||||
			     osmuxh->circuit_id);
 | 
					 | 
				
			||||||
			goto out;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		endp->osmux.stats.octets += osmux_chunk_length(msg, rem);
 | 
					 | 
				
			||||||
		endp->osmux.stats.chunks++;
 | 
					 | 
				
			||||||
		rem = msg->len;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		osmux_xfrm_output(osmuxh, &endp->osmux.out, &list);
 | 
					 | 
				
			||||||
		osmux_tx_sched(&list, scheduled_tx_bts_cb, endp);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
out:
 | 
					 | 
				
			||||||
	msgb_free(msg);
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* This is called from the bsc-nat */
 | 
					 | 
				
			||||||
static int osmux_handle_dummy(struct mgcp_config *cfg, struct sockaddr_in *addr,
 | 
					 | 
				
			||||||
			      struct msgb *msg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct mgcp_endpoint *endp;
 | 
					 | 
				
			||||||
	uint8_t osmux_cid;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (msg->len < 1 + sizeof(osmux_cid)) {
 | 
					 | 
				
			||||||
		LOGP(DLMGCP, LOGL_ERROR,
 | 
					 | 
				
			||||||
		     "Discarding truncated Osmux dummy load\n");
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	LOGP(DLMGCP, LOGL_DEBUG, "Received Osmux dummy load from %s\n",
 | 
					 | 
				
			||||||
	     inet_ntoa(addr->sin_addr));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!cfg->osmux) {
 | 
					 | 
				
			||||||
		LOGP(DLMGCP, LOGL_ERROR,
 | 
					 | 
				
			||||||
		     "bsc wants to use Osmux but bsc-nat did not request it\n");
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* extract the osmux CID from the dummy message */
 | 
					 | 
				
			||||||
	memcpy(&osmux_cid, &msg->data[1], sizeof(osmux_cid));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	endp = endpoint_lookup(cfg, osmux_cid, &addr->sin_addr, MGCP_DEST_BTS);
 | 
					 | 
				
			||||||
	if (!endp) {
 | 
					 | 
				
			||||||
		LOGP(DLMGCP, LOGL_ERROR,
 | 
					 | 
				
			||||||
		     "Cannot find endpoint for Osmux CID %d\n", osmux_cid);
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (endp->osmux.state == OSMUX_STATE_ENABLED)
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (osmux_enable_endpoint(endp, &addr->sin_addr, addr->sin_port) < 0 ) {
 | 
					 | 
				
			||||||
		LOGP(DLMGCP, LOGL_ERROR,
 | 
					 | 
				
			||||||
		     "Could not enable osmux in endpoint %d\n",
 | 
					 | 
				
			||||||
		     ENDPOINT_NUMBER(endp));
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	LOGP(DLMGCP, LOGL_INFO, "Enabling osmux in endpoint %d for %s:%u\n",
 | 
					 | 
				
			||||||
	     ENDPOINT_NUMBER(endp), inet_ntoa(addr->sin_addr),
 | 
					 | 
				
			||||||
	     ntohs(addr->sin_port));
 | 
					 | 
				
			||||||
out:
 | 
					 | 
				
			||||||
	msgb_free(msg);
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int osmux_read_from_bsc_cb(struct osmo_fd *ofd, unsigned int what)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct msgb *msg;
 | 
					 | 
				
			||||||
	struct osmux_hdr *osmuxh;
 | 
					 | 
				
			||||||
	struct llist_head list;
 | 
					 | 
				
			||||||
	struct sockaddr_in addr;
 | 
					 | 
				
			||||||
	struct mgcp_config *cfg = ofd->data;
 | 
					 | 
				
			||||||
	uint32_t rem;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	msg = osmux_recv(ofd, &addr);
 | 
					 | 
				
			||||||
	if (!msg)
 | 
					 | 
				
			||||||
		return -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* not any further processing dummy messages */
 | 
					 | 
				
			||||||
	if (msg->data[0] == MGCP_DUMMY_LOAD)
 | 
					 | 
				
			||||||
		return osmux_handle_dummy(cfg, &addr, msg);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	rem = msg->len;
 | 
					 | 
				
			||||||
	while((osmuxh = osmux_xfrm_output_pull(msg)) != NULL) {
 | 
					 | 
				
			||||||
		struct mgcp_endpoint *endp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* Yes, we use MGCP_DEST_BTS to locate the origin */
 | 
					 | 
				
			||||||
		endp = endpoint_lookup(cfg, osmuxh->circuit_id,
 | 
					 | 
				
			||||||
				       &addr.sin_addr, MGCP_DEST_BTS);
 | 
					 | 
				
			||||||
		if (!endp) {
 | 
					 | 
				
			||||||
			LOGP(DLMGCP, LOGL_ERROR,
 | 
					 | 
				
			||||||
			     "Cannot find an endpoint for circuit_id=%d\n",
 | 
					 | 
				
			||||||
			     osmuxh->circuit_id);
 | 
					 | 
				
			||||||
			goto out;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		endp->osmux.stats.octets += osmux_chunk_length(msg, rem);
 | 
					 | 
				
			||||||
		endp->osmux.stats.chunks++;
 | 
					 | 
				
			||||||
		rem = msg->len;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		osmux_xfrm_output(osmuxh, &endp->osmux.out, &list);
 | 
					 | 
				
			||||||
		osmux_tx_sched(&list, scheduled_tx_net_cb, endp);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
out:
 | 
					 | 
				
			||||||
	msgb_free(msg);
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int osmux_init(int role, struct mgcp_config *cfg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch(role) {
 | 
					 | 
				
			||||||
	case OSMUX_ROLE_BSC:
 | 
					 | 
				
			||||||
		osmux_fd.cb = osmux_read_from_bsc_nat_cb;
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case OSMUX_ROLE_BSC_NAT:
 | 
					 | 
				
			||||||
		osmux_fd.cb = osmux_read_from_bsc_cb;
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		LOGP(DLMGCP, LOGL_ERROR, "wrong role for OSMUX\n");
 | 
					 | 
				
			||||||
		return -1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	osmux_fd.data = cfg;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = mgcp_create_bind(cfg->osmux_addr, &osmux_fd, cfg->osmux_port);
 | 
					 | 
				
			||||||
	if (ret < 0) {
 | 
					 | 
				
			||||||
		LOGP(DLMGCP, LOGL_ERROR, "cannot bind OSMUX socket\n");
 | 
					 | 
				
			||||||
		return ret;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	mgcp_set_ip_tos(osmux_fd.fd, cfg->endp_dscp);
 | 
					 | 
				
			||||||
	osmux_fd.when |= BSC_FD_READ;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = osmo_fd_register(&osmux_fd);
 | 
					 | 
				
			||||||
	if (ret < 0) {
 | 
					 | 
				
			||||||
		LOGP(DLMGCP, LOGL_ERROR, "cannot register OSMUX socket\n");
 | 
					 | 
				
			||||||
		return ret;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	cfg->osmux_init = 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int osmux_enable_endpoint(struct mgcp_endpoint *endp, struct in_addr *addr, uint16_t port)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	/* If osmux is enabled, initialize the output handler. This handler is
 | 
					 | 
				
			||||||
	 * used to reconstruct the RTP flow from osmux. The RTP SSRC is
 | 
					 | 
				
			||||||
	 * allocated based on the circuit ID (endp->osmux.cid), which is unique
 | 
					 | 
				
			||||||
	 * in the local scope to the BSC/BSC-NAT. We use it to divide the RTP
 | 
					 | 
				
			||||||
	 * SSRC space (2^32) by the 256 possible circuit IDs, then randomly
 | 
					 | 
				
			||||||
	 * select one value from that window. Thus, we have no chance to have
 | 
					 | 
				
			||||||
	 * overlapping RTP SSRC traveling to the BTSes behind the BSC,
 | 
					 | 
				
			||||||
	 * similarly, for flows traveling to the MSC.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	static const uint32_t rtp_ssrc_winlen = UINT32_MAX / 256;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (endp->osmux.state == OSMUX_STATE_DISABLED) {
 | 
					 | 
				
			||||||
		LOGP(DLMGCP, LOGL_ERROR, "Endpoint %u didn't request Osmux\n",
 | 
					 | 
				
			||||||
		     ENDPOINT_NUMBER(endp));
 | 
					 | 
				
			||||||
		return -1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	osmux_xfrm_output_init(&endp->osmux.out,
 | 
					 | 
				
			||||||
			       (endp->osmux.cid * rtp_ssrc_winlen) +
 | 
					 | 
				
			||||||
			       (random() % rtp_ssrc_winlen));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	endp->osmux.in = osmux_handle_lookup(endp->cfg, addr, port);
 | 
					 | 
				
			||||||
	if (!endp->osmux.in) {
 | 
					 | 
				
			||||||
		LOGP(DLMGCP, LOGL_ERROR, "Cannot allocate input osmux handle\n");
 | 
					 | 
				
			||||||
		return -1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (!osmux_xfrm_input_open_circuit(endp->osmux.in, endp->osmux.cid,
 | 
					 | 
				
			||||||
					   endp->cfg->osmux_dummy)) {
 | 
					 | 
				
			||||||
		LOGP(DLMGCP, LOGL_ERROR, "Cannot open osmux circuit %u\n",
 | 
					 | 
				
			||||||
		     endp->osmux.cid);
 | 
					 | 
				
			||||||
		return -1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch (endp->cfg->role) {
 | 
					 | 
				
			||||||
		case MGCP_BSC_NAT:
 | 
					 | 
				
			||||||
			endp->type = MGCP_OSMUX_BSC_NAT;
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case MGCP_BSC:
 | 
					 | 
				
			||||||
			endp->type = MGCP_OSMUX_BSC;
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	endp->osmux.state = OSMUX_STATE_ENABLED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void osmux_disable_endpoint(struct mgcp_endpoint *endp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	LOGP(DLMGCP, LOGL_INFO, "Releasing endpoint %u using Osmux CID %u\n",
 | 
					 | 
				
			||||||
	     ENDPOINT_NUMBER(endp), endp->osmux.cid);
 | 
					 | 
				
			||||||
	osmux_xfrm_input_close_circuit(endp->osmux.in, endp->osmux.cid);
 | 
					 | 
				
			||||||
	endp->osmux.state = OSMUX_STATE_DISABLED;
 | 
					 | 
				
			||||||
	endp->osmux.cid = -1;
 | 
					 | 
				
			||||||
	osmux_handle_put(endp->osmux.in);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void osmux_release_cid(struct mgcp_endpoint *endp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (endp->osmux.allocated_cid >= 0)
 | 
					 | 
				
			||||||
		osmux_put_cid(endp->osmux.allocated_cid);
 | 
					 | 
				
			||||||
	endp->osmux.allocated_cid = -1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void osmux_allocate_cid(struct mgcp_endpoint *endp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	osmux_release_cid(endp);
 | 
					 | 
				
			||||||
	endp->osmux.allocated_cid = osmux_get_cid();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* We don't need to send the dummy load for osmux so often as another endpoint
 | 
					 | 
				
			||||||
 * may have already punched the hole in the firewall. This approach is simple
 | 
					 | 
				
			||||||
 * though.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int osmux_send_dummy(struct mgcp_endpoint *endp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	char buf[1 + sizeof(uint8_t)];
 | 
					 | 
				
			||||||
	struct in_addr addr_unset = {};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	buf[0] = MGCP_DUMMY_LOAD;
 | 
					 | 
				
			||||||
	memcpy(&buf[1], &endp->osmux.cid, sizeof(endp->osmux.cid));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Wait until we have the connection information from MDCX */
 | 
					 | 
				
			||||||
	if (memcmp(&endp->net_end.addr, &addr_unset, sizeof(addr_unset)) == 0)
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (endp->osmux.state == OSMUX_STATE_ACTIVATING) {
 | 
					 | 
				
			||||||
		if (osmux_enable_endpoint(endp, &endp->net_end.addr,
 | 
					 | 
				
			||||||
					  htons(endp->cfg->osmux_port)) < 0) {
 | 
					 | 
				
			||||||
			LOGP(DLMGCP, LOGL_ERROR,
 | 
					 | 
				
			||||||
			     "Could not activate osmux in endpoint %d\n",
 | 
					 | 
				
			||||||
			     ENDPOINT_NUMBER(endp));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		LOGP(DLMGCP, LOGL_ERROR,
 | 
					 | 
				
			||||||
		     "Osmux CID %u for %s:%u is now enabled\n",
 | 
					 | 
				
			||||||
		     endp->osmux.cid, inet_ntoa(endp->net_end.addr),
 | 
					 | 
				
			||||||
		     endp->cfg->osmux_port);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	LOGP(DLMGCP, LOGL_DEBUG,
 | 
					 | 
				
			||||||
	     "sending OSMUX dummy load to %s CID %u\n",
 | 
					 | 
				
			||||||
	     inet_ntoa(endp->net_end.addr), endp->osmux.cid);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return mgcp_udp_send(osmux_fd.fd, &endp->net_end.addr,
 | 
					 | 
				
			||||||
			     htons(endp->cfg->osmux_port), buf, sizeof(buf));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* bsc-nat allocates/releases the Osmux circuit ID */
 | 
					 | 
				
			||||||
static uint8_t osmux_cid_bitmap[(OSMUX_CID_MAX + 1) / 8];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int osmux_used_cid(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int i, j, used = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0; i < sizeof(osmux_cid_bitmap); i++) {
 | 
					 | 
				
			||||||
		for (j = 0; j < 8; j++) {
 | 
					 | 
				
			||||||
			if (osmux_cid_bitmap[i] & (1 << j))
 | 
					 | 
				
			||||||
				used += 1;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return used;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int osmux_get_cid(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int i, j;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0; i < sizeof(osmux_cid_bitmap); i++) {
 | 
					 | 
				
			||||||
		for (j = 0; j < 8; j++) {
 | 
					 | 
				
			||||||
			if (osmux_cid_bitmap[i] & (1 << j))
 | 
					 | 
				
			||||||
				continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			osmux_cid_bitmap[i] |= (1 << j);
 | 
					 | 
				
			||||||
			LOGP(DLMGCP, LOGL_DEBUG,
 | 
					 | 
				
			||||||
			     "Allocating Osmux CID %u from pool\n", (i * 8) + j);
 | 
					 | 
				
			||||||
			return (i * 8) + j;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	LOGP(DLMGCP, LOGL_ERROR, "All Osmux circuits are in use!\n");
 | 
					 | 
				
			||||||
	return -1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void osmux_put_cid(uint8_t osmux_cid)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	LOGP(DLMGCP, LOGL_DEBUG, "Osmux CID %u is back to the pool\n", osmux_cid);
 | 
					 | 
				
			||||||
	osmux_cid_bitmap[osmux_cid / 8] &= ~(1 << (osmux_cid % 8));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,305 +0,0 @@
 | 
				
			|||||||
/*
 | 
					 | 
				
			||||||
 * Some SDP file parsing...
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * (C) 2009-2015 by Holger Hans Peter Freyther <zecke@selfish.org>
 | 
					 | 
				
			||||||
 * (C) 2009-2014 by On-Waves
 | 
					 | 
				
			||||||
 * All Rights Reserved
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is free software; you can redistribute it and/or modify
 | 
					 | 
				
			||||||
 * it under the terms of the GNU Affero General Public License as published by
 | 
					 | 
				
			||||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
					 | 
				
			||||||
 * (at your option) any later version.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is distributed in the hope that it will be useful,
 | 
					 | 
				
			||||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 | 
				
			||||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					 | 
				
			||||||
 * GNU Affero General Public License for more details.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * You should have received a copy of the GNU Affero General Public License
 | 
					 | 
				
			||||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <osmocom/legacy_mgcp/mgcp.h>
 | 
					 | 
				
			||||||
#include <osmocom/legacy_mgcp/mgcp_internal.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <errno.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct sdp_rtp_map {
 | 
					 | 
				
			||||||
	/* the type */
 | 
					 | 
				
			||||||
	int payload_type;
 | 
					 | 
				
			||||||
	/* null, static or later dynamic codec name */
 | 
					 | 
				
			||||||
	char *codec_name;
 | 
					 | 
				
			||||||
	/* A pointer to the original line for later parsing */
 | 
					 | 
				
			||||||
	char *map_line;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int rate;
 | 
					 | 
				
			||||||
	int channels;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int mgcp_set_audio_info(void *ctx, struct mgcp_rtp_codec *codec,
 | 
					 | 
				
			||||||
			int payload_type, const char *audio_name)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int rate = codec->rate;
 | 
					 | 
				
			||||||
	int channels = codec->channels;
 | 
					 | 
				
			||||||
	char audio_codec[64];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	talloc_free(codec->subtype_name);
 | 
					 | 
				
			||||||
	codec->subtype_name = NULL;
 | 
					 | 
				
			||||||
	talloc_free(codec->audio_name);
 | 
					 | 
				
			||||||
	codec->audio_name = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (payload_type != PTYPE_UNDEFINED)
 | 
					 | 
				
			||||||
		codec->payload_type = payload_type;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!audio_name) {
 | 
					 | 
				
			||||||
		switch (payload_type) {
 | 
					 | 
				
			||||||
		case 0: audio_name = "PCMU/8000/1"; break;
 | 
					 | 
				
			||||||
		case 3: audio_name = "GSM/8000/1"; break;
 | 
					 | 
				
			||||||
		case 8: audio_name = "PCMA/8000/1"; break;
 | 
					 | 
				
			||||||
		case 18: audio_name = "G729/8000/1"; break;
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			 /* Payload type is unknown, don't change rate and
 | 
					 | 
				
			||||||
			  * channels. */
 | 
					 | 
				
			||||||
			 /* TODO: return value? */
 | 
					 | 
				
			||||||
			 return 0;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (sscanf(audio_name, "%63[^/]/%d/%d",
 | 
					 | 
				
			||||||
		   audio_codec, &rate, &channels) < 1)
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	codec->rate = rate;
 | 
					 | 
				
			||||||
	codec->channels = channels;
 | 
					 | 
				
			||||||
	codec->subtype_name = talloc_strdup(ctx, audio_codec);
 | 
					 | 
				
			||||||
	codec->audio_name = talloc_strdup(ctx, audio_name);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!strcmp(audio_codec, "G729")) {
 | 
					 | 
				
			||||||
		codec->frame_duration_num = 10;
 | 
					 | 
				
			||||||
		codec->frame_duration_den = 1000;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		codec->frame_duration_num = DEFAULT_RTP_AUDIO_FRAME_DUR_NUM;
 | 
					 | 
				
			||||||
		codec->frame_duration_den = DEFAULT_RTP_AUDIO_FRAME_DUR_DEN;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (payload_type < 0) {
 | 
					 | 
				
			||||||
		payload_type = 96;
 | 
					 | 
				
			||||||
		if (rate == 8000 && channels == 1) {
 | 
					 | 
				
			||||||
			if (!strcmp(audio_codec, "GSM"))
 | 
					 | 
				
			||||||
				payload_type = 3;
 | 
					 | 
				
			||||||
			else if (!strcmp(audio_codec, "PCMA"))
 | 
					 | 
				
			||||||
				payload_type = 8;
 | 
					 | 
				
			||||||
			else if (!strcmp(audio_codec, "PCMU"))
 | 
					 | 
				
			||||||
				payload_type = 0;
 | 
					 | 
				
			||||||
			else if (!strcmp(audio_codec, "G729"))
 | 
					 | 
				
			||||||
				payload_type = 18;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		codec->payload_type = payload_type;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (channels != 1)
 | 
					 | 
				
			||||||
		LOGP(DLMGCP, LOGL_NOTICE,
 | 
					 | 
				
			||||||
		     "Channels != 1 in SDP: '%s'\n", audio_name);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void codecs_initialize(void *ctx, struct sdp_rtp_map *codecs, int used)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0; i < used; ++i) {
 | 
					 | 
				
			||||||
		switch (codecs[i].payload_type) {
 | 
					 | 
				
			||||||
		case 0:
 | 
					 | 
				
			||||||
			codecs[i].codec_name = "PCMU";
 | 
					 | 
				
			||||||
			codecs[i].rate = 8000;
 | 
					 | 
				
			||||||
			codecs[i].channels = 1;
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case 3:
 | 
					 | 
				
			||||||
			codecs[i].codec_name = "GSM";
 | 
					 | 
				
			||||||
			codecs[i].rate = 8000;
 | 
					 | 
				
			||||||
			codecs[i].channels = 1;
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case 8:
 | 
					 | 
				
			||||||
			codecs[i].codec_name = "PCMA";
 | 
					 | 
				
			||||||
			codecs[i].rate = 8000;
 | 
					 | 
				
			||||||
			codecs[i].channels = 1;
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case 18:
 | 
					 | 
				
			||||||
			codecs[i].codec_name = "G729";
 | 
					 | 
				
			||||||
			codecs[i].rate = 8000;
 | 
					 | 
				
			||||||
			codecs[i].channels = 1;
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void codecs_update(void *ctx, struct sdp_rtp_map *codecs, int used, int payload, char *audio_name)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0; i < used; ++i) {
 | 
					 | 
				
			||||||
		char audio_codec[64];
 | 
					 | 
				
			||||||
		int rate = -1;
 | 
					 | 
				
			||||||
		int channels = -1;
 | 
					 | 
				
			||||||
		if (codecs[i].payload_type != payload)
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
		if (sscanf(audio_name, "%63[^/]/%d/%d",
 | 
					 | 
				
			||||||
				audio_codec, &rate, &channels) < 1) {
 | 
					 | 
				
			||||||
			LOGP(DLMGCP, LOGL_ERROR, "Failed to parse '%s'\n", audio_name);
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		codecs[i].map_line = talloc_strdup(ctx, audio_name);
 | 
					 | 
				
			||||||
		codecs[i].codec_name = talloc_strdup(ctx, audio_codec);
 | 
					 | 
				
			||||||
		codecs[i].rate = rate;
 | 
					 | 
				
			||||||
		codecs[i].channels = channels;
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	LOGP(DLMGCP, LOGL_ERROR, "Unconfigured PT(%d) with %s\n", payload, audio_name);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int is_codec_compatible(struct mgcp_endpoint *endp, struct sdp_rtp_map *codec)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	char *bts_codec;
 | 
					 | 
				
			||||||
	char audio_codec[64];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!codec->codec_name)
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * GSM, GSM/8000 and GSM/8000/1 should all be compatible.. let's go
 | 
					 | 
				
			||||||
	 * by name first.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	bts_codec = endp->tcfg->audio_name;
 | 
					 | 
				
			||||||
	if (sscanf(bts_codec, "%63[^/]/%*d/%*d", audio_codec) < 1)
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return strcasecmp(audio_codec, codec->codec_name) == 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int mgcp_parse_sdp_data(struct mgcp_endpoint *endp, struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct sdp_rtp_map codecs[10];
 | 
					 | 
				
			||||||
	int codecs_used = 0;
 | 
					 | 
				
			||||||
	char *line;
 | 
					 | 
				
			||||||
	int maxptime = -1;
 | 
					 | 
				
			||||||
	int i;
 | 
					 | 
				
			||||||
	int codecs_assigned = 0;
 | 
					 | 
				
			||||||
	void *tmp_ctx = talloc_new(NULL);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	memset(&codecs, 0, sizeof(codecs));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for_each_line(line, p->save) {
 | 
					 | 
				
			||||||
		switch (line[0]) {
 | 
					 | 
				
			||||||
		case 'o':
 | 
					 | 
				
			||||||
		case 's':
 | 
					 | 
				
			||||||
		case 't':
 | 
					 | 
				
			||||||
		case 'v':
 | 
					 | 
				
			||||||
			/* skip these SDP attributes */
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case 'a': {
 | 
					 | 
				
			||||||
			int payload;
 | 
					 | 
				
			||||||
			int ptime, ptime2 = 0;
 | 
					 | 
				
			||||||
			char audio_name[64];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (sscanf(line, "a=rtpmap:%d %63s",
 | 
					 | 
				
			||||||
				   &payload, audio_name) == 2) {
 | 
					 | 
				
			||||||
				codecs_update(tmp_ctx, codecs, codecs_used, payload, audio_name);
 | 
					 | 
				
			||||||
			} else if (sscanf(line, "a=ptime:%d-%d",
 | 
					 | 
				
			||||||
					  &ptime, &ptime2) >= 1) {
 | 
					 | 
				
			||||||
				if (ptime2 > 0 && ptime2 != ptime)
 | 
					 | 
				
			||||||
					rtp->packet_duration_ms = 0;
 | 
					 | 
				
			||||||
				else
 | 
					 | 
				
			||||||
					rtp->packet_duration_ms = ptime;
 | 
					 | 
				
			||||||
			} else if (sscanf(line, "a=maxptime:%d", &ptime2) == 1) {
 | 
					 | 
				
			||||||
				maxptime = ptime2;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		case 'm': {
 | 
					 | 
				
			||||||
			int port, rc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			rc = sscanf(line, "m=audio %d RTP/AVP %d %d %d %d %d %d %d %d %d %d",
 | 
					 | 
				
			||||||
					&port,
 | 
					 | 
				
			||||||
					&codecs[0].payload_type,
 | 
					 | 
				
			||||||
					&codecs[1].payload_type,
 | 
					 | 
				
			||||||
					&codecs[2].payload_type,
 | 
					 | 
				
			||||||
					&codecs[3].payload_type,
 | 
					 | 
				
			||||||
					&codecs[4].payload_type,
 | 
					 | 
				
			||||||
					&codecs[5].payload_type,
 | 
					 | 
				
			||||||
					&codecs[6].payload_type,
 | 
					 | 
				
			||||||
					&codecs[7].payload_type,
 | 
					 | 
				
			||||||
					&codecs[8].payload_type,
 | 
					 | 
				
			||||||
					&codecs[9].payload_type);
 | 
					 | 
				
			||||||
			if (rc >= 2) {
 | 
					 | 
				
			||||||
				rtp->rtp_port = htons(port);
 | 
					 | 
				
			||||||
				rtp->rtcp_port = htons(port + 1);
 | 
					 | 
				
			||||||
				codecs_used = rc - 1;
 | 
					 | 
				
			||||||
				codecs_initialize(tmp_ctx, codecs, codecs_used);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		case 'c': {
 | 
					 | 
				
			||||||
			char ipv4[16];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (sscanf(line, "c=IN IP4 %15s", ipv4) == 1) {
 | 
					 | 
				
			||||||
				inet_aton(ipv4, &rtp->addr);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			if (p->endp)
 | 
					 | 
				
			||||||
				LOGP(DLMGCP, LOGL_NOTICE,
 | 
					 | 
				
			||||||
				     "Unhandled SDP option: '%c'/%d on 0x%x\n",
 | 
					 | 
				
			||||||
				     line[0], line[0], ENDPOINT_NUMBER(p->endp));
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
				LOGP(DLMGCP, LOGL_NOTICE,
 | 
					 | 
				
			||||||
				     "Unhandled SDP option: '%c'/%d\n",
 | 
					 | 
				
			||||||
				     line[0], line[0]);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Now select the primary and alt_codec */
 | 
					 | 
				
			||||||
	for (i = 0; i < codecs_used && codecs_assigned < 2; ++i) {
 | 
					 | 
				
			||||||
		struct mgcp_rtp_codec *codec = codecs_assigned == 0 ?
 | 
					 | 
				
			||||||
					&rtp->codec : &rtp->alt_codec;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (endp->tcfg->no_audio_transcoding &&
 | 
					 | 
				
			||||||
			!is_codec_compatible(endp, &codecs[i])) {
 | 
					 | 
				
			||||||
			LOGP(DLMGCP, LOGL_NOTICE, "Skipping codec %s\n",
 | 
					 | 
				
			||||||
				codecs[i].codec_name);
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		mgcp_set_audio_info(p->cfg, codec,
 | 
					 | 
				
			||||||
					codecs[i].payload_type,
 | 
					 | 
				
			||||||
					codecs[i].map_line);
 | 
					 | 
				
			||||||
		codecs_assigned += 1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (codecs_assigned > 0) {
 | 
					 | 
				
			||||||
		/* TODO/XXX: Store this per codec and derive it on use */
 | 
					 | 
				
			||||||
		if (maxptime >= 0 && maxptime * rtp->codec.frame_duration_den >
 | 
					 | 
				
			||||||
				rtp->codec.frame_duration_num * 1500) {
 | 
					 | 
				
			||||||
			/* more than 1 frame */
 | 
					 | 
				
			||||||
			rtp->packet_duration_ms = 0;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		LOGP(DLMGCP, LOGL_NOTICE,
 | 
					 | 
				
			||||||
		     "Got media info via SDP: port %d, payload %d (%s), "
 | 
					 | 
				
			||||||
		     "duration %d, addr %s\n",
 | 
					 | 
				
			||||||
		     ntohs(rtp->rtp_port), rtp->codec.payload_type,
 | 
					 | 
				
			||||||
		     rtp->codec.subtype_name ? rtp->codec.subtype_name : "unknown",
 | 
					 | 
				
			||||||
		     rtp->packet_duration_ms, inet_ntoa(rtp->addr));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	talloc_free(tmp_ctx);
 | 
					 | 
				
			||||||
	return codecs_assigned > 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@@ -1,611 +0,0 @@
 | 
				
			|||||||
/*
 | 
					 | 
				
			||||||
 * (C) 2014 by On-Waves
 | 
					 | 
				
			||||||
 * All Rights Reserved
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is free software; you can redistribute it and/or modify
 | 
					 | 
				
			||||||
 * it under the terms of the GNU Affero General Public License as published by
 | 
					 | 
				
			||||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
					 | 
				
			||||||
 * (at your option) any later version.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is distributed in the hope that it will be useful,
 | 
					 | 
				
			||||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 | 
				
			||||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					 | 
				
			||||||
 * GNU Affero General Public License for more details.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * You should have received a copy of the GNU Affero General Public License
 | 
					 | 
				
			||||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
#include <errno.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "g711common.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <osmocom/legacy_mgcp/mgcp.h>
 | 
					 | 
				
			||||||
#include <osmocom/legacy_mgcp/mgcp_internal.h>
 | 
					 | 
				
			||||||
#include <osmocom/legacy_mgcp/mgcp_transcode.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <osmocom/core/talloc.h>
 | 
					 | 
				
			||||||
#include <osmocom/netif/rtp.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int mgcp_transcoding_get_frame_size(void *state_, int nsamples, int dst)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct mgcp_process_rtp_state *state = state_;
 | 
					 | 
				
			||||||
	if (dst)
 | 
					 | 
				
			||||||
		return (nsamples >= 0 ?
 | 
					 | 
				
			||||||
			nsamples / state->dst_samples_per_frame :
 | 
					 | 
				
			||||||
			1) * state->dst_frame_size;
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		return (nsamples >= 0 ?
 | 
					 | 
				
			||||||
			nsamples / state->src_samples_per_frame :
 | 
					 | 
				
			||||||
			1) * state->src_frame_size;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static enum audio_format get_audio_format(const struct mgcp_rtp_codec *codec)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (codec->subtype_name) {
 | 
					 | 
				
			||||||
		if (!strcasecmp("GSM", codec->subtype_name))
 | 
					 | 
				
			||||||
			return AF_GSM;
 | 
					 | 
				
			||||||
		if (!strcasecmp("PCMA", codec->subtype_name))
 | 
					 | 
				
			||||||
			return AF_PCMA;
 | 
					 | 
				
			||||||
		if (!strcasecmp("PCMU", codec->subtype_name))
 | 
					 | 
				
			||||||
			return AF_PCMU;
 | 
					 | 
				
			||||||
#ifdef HAVE_BCG729
 | 
					 | 
				
			||||||
		if (!strcasecmp("G729", codec->subtype_name))
 | 
					 | 
				
			||||||
			return AF_G729;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
		if (!strcasecmp("L16", codec->subtype_name))
 | 
					 | 
				
			||||||
			return AF_L16;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch (codec->payload_type) {
 | 
					 | 
				
			||||||
	case 0 /* PCMU */:
 | 
					 | 
				
			||||||
		return AF_PCMU;
 | 
					 | 
				
			||||||
	case 3 /* GSM */:
 | 
					 | 
				
			||||||
		return AF_GSM;
 | 
					 | 
				
			||||||
	case 8 /* PCMA */:
 | 
					 | 
				
			||||||
		return AF_PCMA;
 | 
					 | 
				
			||||||
#ifdef HAVE_BCG729
 | 
					 | 
				
			||||||
	case 18 /* G.729 */:
 | 
					 | 
				
			||||||
		return AF_G729;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	case 11 /* L16 */:
 | 
					 | 
				
			||||||
		return AF_L16;
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		return AF_INVALID;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void l16_encode(short *sample, unsigned char *buf, size_t n)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	for (; n > 0; --n, ++sample, buf += 2) {
 | 
					 | 
				
			||||||
		buf[0] = sample[0] >> 8;
 | 
					 | 
				
			||||||
		buf[1] = sample[0] & 0xff;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void l16_decode(unsigned char *buf, short *sample, size_t n)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	for (; n > 0; --n, ++sample, buf += 2)
 | 
					 | 
				
			||||||
		sample[0] = ((short)buf[0] << 8) | buf[1];
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void alaw_encode(short *sample, unsigned char *buf, size_t n)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	for (; n > 0; --n)
 | 
					 | 
				
			||||||
		*(buf++) = s16_to_alaw(*(sample++));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void alaw_decode(unsigned char *buf, short *sample, size_t n)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	for (; n > 0; --n)
 | 
					 | 
				
			||||||
		*(sample++) = alaw_to_s16(*(buf++));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void ulaw_encode(short *sample, unsigned char *buf, size_t n)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	for (; n > 0; --n)
 | 
					 | 
				
			||||||
		*(buf++) = s16_to_ulaw(*(sample++));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void ulaw_decode(unsigned char *buf, short *sample, size_t n)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	for (; n > 0; --n)
 | 
					 | 
				
			||||||
		*(sample++) = ulaw_to_s16(*(buf++));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int processing_state_destructor(struct mgcp_process_rtp_state *state)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	switch (state->src_fmt) {
 | 
					 | 
				
			||||||
	case AF_GSM:
 | 
					 | 
				
			||||||
		if (state->src.gsm_handle)
 | 
					 | 
				
			||||||
			gsm_destroy(state->src.gsm_handle);
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
#ifdef HAVE_BCG729
 | 
					 | 
				
			||||||
	case AF_G729:
 | 
					 | 
				
			||||||
		if (state->src.g729_dec)
 | 
					 | 
				
			||||||
			closeBcg729DecoderChannel(state->src.g729_dec);
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	switch (state->dst_fmt) {
 | 
					 | 
				
			||||||
	case AF_GSM:
 | 
					 | 
				
			||||||
		if (state->dst.gsm_handle)
 | 
					 | 
				
			||||||
			gsm_destroy(state->dst.gsm_handle);
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
#ifdef HAVE_BCG729
 | 
					 | 
				
			||||||
	case AF_G729:
 | 
					 | 
				
			||||||
		if (state->dst.g729_enc)
 | 
					 | 
				
			||||||
			closeBcg729EncoderChannel(state->dst.g729_enc);
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int mgcp_transcoding_setup(struct mgcp_endpoint *endp,
 | 
					 | 
				
			||||||
			   struct mgcp_rtp_end *dst_end,
 | 
					 | 
				
			||||||
			   struct mgcp_rtp_end *src_end)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct mgcp_process_rtp_state *state;
 | 
					 | 
				
			||||||
	enum audio_format src_fmt, dst_fmt;
 | 
					 | 
				
			||||||
	const struct mgcp_rtp_codec *dst_codec = &dst_end->codec;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* cleanup first */
 | 
					 | 
				
			||||||
	if (dst_end->rtp_process_data) {
 | 
					 | 
				
			||||||
		talloc_free(dst_end->rtp_process_data);
 | 
					 | 
				
			||||||
		dst_end->rtp_process_data = NULL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!src_end)
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const struct mgcp_rtp_codec *src_codec = &src_end->codec;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (endp->tcfg->no_audio_transcoding) {
 | 
					 | 
				
			||||||
		LOGP(DLMGCP, LOGL_NOTICE,
 | 
					 | 
				
			||||||
			"Transcoding disabled on endpoint 0x%x\n",
 | 
					 | 
				
			||||||
			ENDPOINT_NUMBER(endp));
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	src_fmt = get_audio_format(src_codec);
 | 
					 | 
				
			||||||
	dst_fmt = get_audio_format(dst_codec);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	LOGP(DLMGCP, LOGL_ERROR,
 | 
					 | 
				
			||||||
	     "Checking transcoding: %s (%d) -> %s (%d)\n",
 | 
					 | 
				
			||||||
	     src_codec->subtype_name, src_codec->payload_type,
 | 
					 | 
				
			||||||
	     dst_codec->subtype_name, dst_codec->payload_type);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (src_fmt == AF_INVALID || dst_fmt == AF_INVALID) {
 | 
					 | 
				
			||||||
		if (!src_codec->subtype_name || !dst_codec->subtype_name)
 | 
					 | 
				
			||||||
			/* Not enough info, do nothing */
 | 
					 | 
				
			||||||
			return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (strcasecmp(src_codec->subtype_name, dst_codec->subtype_name) == 0)
 | 
					 | 
				
			||||||
			/* Nothing to do */
 | 
					 | 
				
			||||||
			return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		LOGP(DLMGCP, LOGL_ERROR,
 | 
					 | 
				
			||||||
		     "Cannot transcode: %s codec not supported (%s -> %s).\n",
 | 
					 | 
				
			||||||
		     src_fmt != AF_INVALID ? "destination" : "source",
 | 
					 | 
				
			||||||
		     src_codec->audio_name, dst_codec->audio_name);
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (src_codec->rate && dst_codec->rate && src_codec->rate != dst_codec->rate) {
 | 
					 | 
				
			||||||
		LOGP(DLMGCP, LOGL_ERROR,
 | 
					 | 
				
			||||||
		     "Cannot transcode: rate conversion (%d -> %d) not supported.\n",
 | 
					 | 
				
			||||||
		     src_codec->rate, dst_codec->rate);
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	state = talloc_zero(endp->tcfg->cfg, struct mgcp_process_rtp_state);
 | 
					 | 
				
			||||||
	talloc_set_destructor(state, processing_state_destructor);
 | 
					 | 
				
			||||||
	dst_end->rtp_process_data = state;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	state->src_fmt = src_fmt;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch (state->src_fmt) {
 | 
					 | 
				
			||||||
	case AF_L16:
 | 
					 | 
				
			||||||
	case AF_S16:
 | 
					 | 
				
			||||||
		state->src_frame_size = 80 * sizeof(short);
 | 
					 | 
				
			||||||
		state->src_samples_per_frame = 80;
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case AF_GSM:
 | 
					 | 
				
			||||||
		state->src_frame_size = sizeof(gsm_frame);
 | 
					 | 
				
			||||||
		state->src_samples_per_frame = 160;
 | 
					 | 
				
			||||||
		state->src.gsm_handle = gsm_create();
 | 
					 | 
				
			||||||
		if (!state->src.gsm_handle) {
 | 
					 | 
				
			||||||
			LOGP(DLMGCP, LOGL_ERROR,
 | 
					 | 
				
			||||||
			     "Failed to initialize GSM decoder.\n");
 | 
					 | 
				
			||||||
			return -EINVAL;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
#ifdef HAVE_BCG729
 | 
					 | 
				
			||||||
	case AF_G729:
 | 
					 | 
				
			||||||
		state->src_frame_size = 10;
 | 
					 | 
				
			||||||
		state->src_samples_per_frame = 80;
 | 
					 | 
				
			||||||
		state->src.g729_dec = initBcg729DecoderChannel();
 | 
					 | 
				
			||||||
		if (!state->src.g729_dec) {
 | 
					 | 
				
			||||||
			LOGP(DLMGCP, LOGL_ERROR,
 | 
					 | 
				
			||||||
			     "Failed to initialize G.729 decoder.\n");
 | 
					 | 
				
			||||||
			return -EINVAL;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	case AF_PCMU:
 | 
					 | 
				
			||||||
	case AF_PCMA:
 | 
					 | 
				
			||||||
		state->src_frame_size = 80;
 | 
					 | 
				
			||||||
		state->src_samples_per_frame = 80;
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	state->dst_fmt = dst_fmt;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch (state->dst_fmt) {
 | 
					 | 
				
			||||||
	case AF_L16:
 | 
					 | 
				
			||||||
	case AF_S16:
 | 
					 | 
				
			||||||
		state->dst_frame_size = 80*sizeof(short);
 | 
					 | 
				
			||||||
		state->dst_samples_per_frame = 80;
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case AF_GSM:
 | 
					 | 
				
			||||||
		state->dst_frame_size = sizeof(gsm_frame);
 | 
					 | 
				
			||||||
		state->dst_samples_per_frame = 160;
 | 
					 | 
				
			||||||
		state->dst.gsm_handle = gsm_create();
 | 
					 | 
				
			||||||
		if (!state->dst.gsm_handle) {
 | 
					 | 
				
			||||||
			LOGP(DLMGCP, LOGL_ERROR,
 | 
					 | 
				
			||||||
			     "Failed to initialize GSM encoder.\n");
 | 
					 | 
				
			||||||
			return -EINVAL;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
#ifdef HAVE_BCG729
 | 
					 | 
				
			||||||
	case AF_G729:
 | 
					 | 
				
			||||||
		state->dst_frame_size = 10;
 | 
					 | 
				
			||||||
		state->dst_samples_per_frame = 80;
 | 
					 | 
				
			||||||
		state->dst.g729_enc = initBcg729EncoderChannel();
 | 
					 | 
				
			||||||
		if (!state->dst.g729_enc) {
 | 
					 | 
				
			||||||
			LOGP(DLMGCP, LOGL_ERROR,
 | 
					 | 
				
			||||||
			     "Failed to initialize G.729 decoder.\n");
 | 
					 | 
				
			||||||
			return -EINVAL;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	case AF_PCMU:
 | 
					 | 
				
			||||||
	case AF_PCMA:
 | 
					 | 
				
			||||||
		state->dst_frame_size = 80;
 | 
					 | 
				
			||||||
		state->dst_samples_per_frame = 80;
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (dst_end->force_output_ptime)
 | 
					 | 
				
			||||||
		state->dst_packet_duration = mgcp_rtp_packet_duration(endp, dst_end);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	LOGP(DLMGCP, LOGL_INFO,
 | 
					 | 
				
			||||||
	     "Initialized RTP processing on: 0x%x "
 | 
					 | 
				
			||||||
	     "conv: %d (%d, %d, %s) -> %d (%d, %d, %s)\n",
 | 
					 | 
				
			||||||
	     ENDPOINT_NUMBER(endp),
 | 
					 | 
				
			||||||
	     src_fmt, src_codec->payload_type, src_codec->rate, src_end->fmtp_extra,
 | 
					 | 
				
			||||||
	     dst_fmt, dst_codec->payload_type, dst_codec->rate, dst_end->fmtp_extra);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void mgcp_transcoding_net_downlink_format(struct mgcp_endpoint *endp,
 | 
					 | 
				
			||||||
					  int *payload_type,
 | 
					 | 
				
			||||||
					  const char**audio_name,
 | 
					 | 
				
			||||||
					  const char**fmtp_extra)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct mgcp_process_rtp_state *state = endp->net_end.rtp_process_data;
 | 
					 | 
				
			||||||
	struct mgcp_rtp_codec *net_codec = &endp->net_end.codec;
 | 
					 | 
				
			||||||
	struct mgcp_rtp_codec *bts_codec = &endp->bts_end.codec;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!state || net_codec->payload_type < 0) {
 | 
					 | 
				
			||||||
		*payload_type = bts_codec->payload_type;
 | 
					 | 
				
			||||||
		*audio_name = bts_codec->audio_name;
 | 
					 | 
				
			||||||
		*fmtp_extra = endp->bts_end.fmtp_extra;
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	*payload_type = net_codec->payload_type;
 | 
					 | 
				
			||||||
	*audio_name = net_codec->audio_name;
 | 
					 | 
				
			||||||
	*fmtp_extra = endp->net_end.fmtp_extra;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int decode_audio(struct mgcp_process_rtp_state *state,
 | 
					 | 
				
			||||||
			uint8_t **src, size_t *nbytes)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	while (*nbytes >= state->src_frame_size) {
 | 
					 | 
				
			||||||
		if (state->sample_cnt + state->src_samples_per_frame > ARRAY_SIZE(state->samples)) {
 | 
					 | 
				
			||||||
			LOGP(DLMGCP, LOGL_ERROR,
 | 
					 | 
				
			||||||
			     "Sample buffer too small: %zu > %zu.\n",
 | 
					 | 
				
			||||||
			     state->sample_cnt + state->src_samples_per_frame,
 | 
					 | 
				
			||||||
			     ARRAY_SIZE(state->samples));
 | 
					 | 
				
			||||||
			return -ENOSPC;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		switch (state->src_fmt) {
 | 
					 | 
				
			||||||
		case AF_GSM:
 | 
					 | 
				
			||||||
			if (gsm_decode(state->src.gsm_handle,
 | 
					 | 
				
			||||||
				       (gsm_byte *)*src, state->samples + state->sample_cnt) < 0) {
 | 
					 | 
				
			||||||
				LOGP(DLMGCP, LOGL_ERROR,
 | 
					 | 
				
			||||||
				     "Failed to decode GSM.\n");
 | 
					 | 
				
			||||||
				return -EINVAL;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
#ifdef HAVE_BCG729
 | 
					 | 
				
			||||||
		case AF_G729:
 | 
					 | 
				
			||||||
			bcg729Decoder(state->src.g729_dec, *src, 0, state->samples + state->sample_cnt);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
		case AF_PCMU:
 | 
					 | 
				
			||||||
			ulaw_decode(*src, state->samples + state->sample_cnt,
 | 
					 | 
				
			||||||
				    state->src_samples_per_frame);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case AF_PCMA:
 | 
					 | 
				
			||||||
			alaw_decode(*src, state->samples + state->sample_cnt,
 | 
					 | 
				
			||||||
				    state->src_samples_per_frame);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case AF_S16:
 | 
					 | 
				
			||||||
			memmove(state->samples + state->sample_cnt, *src,
 | 
					 | 
				
			||||||
				state->src_frame_size);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case AF_L16:
 | 
					 | 
				
			||||||
			l16_decode(*src, state->samples + state->sample_cnt,
 | 
					 | 
				
			||||||
				   state->src_samples_per_frame);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		*src        += state->src_frame_size;
 | 
					 | 
				
			||||||
		*nbytes     -= state->src_frame_size;
 | 
					 | 
				
			||||||
		state->sample_cnt += state->src_samples_per_frame;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int encode_audio(struct mgcp_process_rtp_state *state,
 | 
					 | 
				
			||||||
			uint8_t *dst, size_t buf_size, size_t max_samples)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int nbytes = 0;
 | 
					 | 
				
			||||||
	size_t nsamples = 0;
 | 
					 | 
				
			||||||
	/* Encode samples into dst */
 | 
					 | 
				
			||||||
	while (nsamples + state->dst_samples_per_frame <= max_samples) {
 | 
					 | 
				
			||||||
		if (nbytes + state->dst_frame_size > buf_size) {
 | 
					 | 
				
			||||||
			if (nbytes > 0)
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			/* Not even one frame fits into the buffer */
 | 
					 | 
				
			||||||
			LOGP(DLMGCP, LOGL_INFO,
 | 
					 | 
				
			||||||
			     "Encoding (RTP) buffer too small: %zu > %zu.\n",
 | 
					 | 
				
			||||||
			     nbytes + state->dst_frame_size, buf_size);
 | 
					 | 
				
			||||||
			return -ENOSPC;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		switch (state->dst_fmt) {
 | 
					 | 
				
			||||||
		case AF_GSM:
 | 
					 | 
				
			||||||
			gsm_encode(state->dst.gsm_handle,
 | 
					 | 
				
			||||||
				   state->samples + state->sample_offs, dst);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
#ifdef HAVE_BCG729
 | 
					 | 
				
			||||||
		case AF_G729:
 | 
					 | 
				
			||||||
			bcg729Encoder(state->dst.g729_enc,
 | 
					 | 
				
			||||||
				      state->samples + state->sample_offs, dst);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
		case AF_PCMU:
 | 
					 | 
				
			||||||
			ulaw_encode(state->samples + state->sample_offs, dst,
 | 
					 | 
				
			||||||
				    state->src_samples_per_frame);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case AF_PCMA:
 | 
					 | 
				
			||||||
			alaw_encode(state->samples + state->sample_offs, dst,
 | 
					 | 
				
			||||||
				    state->src_samples_per_frame);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case AF_S16:
 | 
					 | 
				
			||||||
			memmove(dst, state->samples + state->sample_offs,
 | 
					 | 
				
			||||||
				state->dst_frame_size);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case AF_L16:
 | 
					 | 
				
			||||||
			l16_encode(state->samples + state->sample_offs, dst,
 | 
					 | 
				
			||||||
				   state->src_samples_per_frame);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		dst        += state->dst_frame_size;
 | 
					 | 
				
			||||||
		nbytes     += state->dst_frame_size;
 | 
					 | 
				
			||||||
		state->sample_offs += state->dst_samples_per_frame;
 | 
					 | 
				
			||||||
		nsamples   += state->dst_samples_per_frame;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	state->sample_cnt -= nsamples;
 | 
					 | 
				
			||||||
	return nbytes;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct mgcp_rtp_end *source_for_dest(struct mgcp_endpoint *endp,
 | 
					 | 
				
			||||||
					struct mgcp_rtp_end *dst_end)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (&endp->bts_end == dst_end)
 | 
					 | 
				
			||||||
		return &endp->net_end;
 | 
					 | 
				
			||||||
	else if (&endp->net_end == dst_end)
 | 
					 | 
				
			||||||
		return &endp->bts_end;
 | 
					 | 
				
			||||||
	OSMO_ASSERT(0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * With some modems we get offered multiple codecs
 | 
					 | 
				
			||||||
 * and we have selected one of them. It might not
 | 
					 | 
				
			||||||
 * be the right one and we need to detect this with
 | 
					 | 
				
			||||||
 * the first audio packets. One difficulty is that
 | 
					 | 
				
			||||||
 * we patch the rtp payload type in place, so we
 | 
					 | 
				
			||||||
 * need to discuss this.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
struct mgcp_process_rtp_state *check_transcode_state(
 | 
					 | 
				
			||||||
				struct mgcp_endpoint *endp,
 | 
					 | 
				
			||||||
				struct mgcp_rtp_end *dst_end,
 | 
					 | 
				
			||||||
				struct rtp_hdr *rtp_hdr)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct mgcp_rtp_end *src_end;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Only deal with messages from net to bts */
 | 
					 | 
				
			||||||
	if (&endp->bts_end != dst_end)
 | 
					 | 
				
			||||||
		goto done;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	src_end = source_for_dest(endp, dst_end);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Already patched */
 | 
					 | 
				
			||||||
	if (rtp_hdr->payload_type == dst_end->codec.payload_type)
 | 
					 | 
				
			||||||
		goto done;
 | 
					 | 
				
			||||||
	/* The payload we expect */
 | 
					 | 
				
			||||||
	if (rtp_hdr->payload_type == src_end->codec.payload_type)
 | 
					 | 
				
			||||||
		goto done;
 | 
					 | 
				
			||||||
	/* The matching alternate payload type? Then switch */
 | 
					 | 
				
			||||||
	if (rtp_hdr->payload_type == src_end->alt_codec.payload_type) {
 | 
					 | 
				
			||||||
		struct mgcp_config *cfg = endp->cfg;
 | 
					 | 
				
			||||||
		struct mgcp_rtp_codec tmp_codec = src_end->alt_codec;
 | 
					 | 
				
			||||||
		src_end->alt_codec = src_end->codec;
 | 
					 | 
				
			||||||
		src_end->codec = tmp_codec;
 | 
					 | 
				
			||||||
		cfg->setup_rtp_processing_cb(endp, &endp->net_end, &endp->bts_end);
 | 
					 | 
				
			||||||
		cfg->setup_rtp_processing_cb(endp, &endp->bts_end, &endp->net_end);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
done:
 | 
					 | 
				
			||||||
	return dst_end->rtp_process_data;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int mgcp_transcoding_process_rtp(struct mgcp_endpoint *endp,
 | 
					 | 
				
			||||||
				struct mgcp_rtp_end *dst_end,
 | 
					 | 
				
			||||||
			     char *data, int *len, int buf_size)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct mgcp_process_rtp_state *state;
 | 
					 | 
				
			||||||
	const size_t rtp_hdr_size = sizeof(struct rtp_hdr);
 | 
					 | 
				
			||||||
	struct rtp_hdr *rtp_hdr = (struct rtp_hdr *) data;
 | 
					 | 
				
			||||||
	char *payload_data = (char *) &rtp_hdr->data[0];
 | 
					 | 
				
			||||||
	int payload_len = *len - rtp_hdr_size;
 | 
					 | 
				
			||||||
	uint8_t *src = (uint8_t *)payload_data;
 | 
					 | 
				
			||||||
	uint8_t *dst = (uint8_t *)payload_data;
 | 
					 | 
				
			||||||
	size_t nbytes = payload_len;
 | 
					 | 
				
			||||||
	size_t nsamples;
 | 
					 | 
				
			||||||
	size_t max_samples;
 | 
					 | 
				
			||||||
	uint32_t ts_no;
 | 
					 | 
				
			||||||
	int rc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	state = check_transcode_state(endp, dst_end, rtp_hdr);
 | 
					 | 
				
			||||||
	if (!state)
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (state->src_fmt == state->dst_fmt) {
 | 
					 | 
				
			||||||
		if (!state->dst_packet_duration)
 | 
					 | 
				
			||||||
			return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* TODO: repackage without transcoding */
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* If the remaining samples do not fit into a fixed ptime,
 | 
					 | 
				
			||||||
	 * a) discard them, if the next packet is much later
 | 
					 | 
				
			||||||
	 * b) add silence and * send it, if the current packet is not
 | 
					 | 
				
			||||||
	 *    yet too late
 | 
					 | 
				
			||||||
	 * c) append the sample data, if the timestamp matches exactly
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* TODO: check payload type (-> G.711 comfort noise) */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (payload_len > 0) {
 | 
					 | 
				
			||||||
		ts_no = ntohl(rtp_hdr->timestamp);
 | 
					 | 
				
			||||||
		if (!state->is_running) {
 | 
					 | 
				
			||||||
			state->next_seq = ntohs(rtp_hdr->sequence);
 | 
					 | 
				
			||||||
			state->next_time = ts_no;
 | 
					 | 
				
			||||||
			state->is_running = 1;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (state->sample_cnt > 0) {
 | 
					 | 
				
			||||||
			int32_t delta = ts_no - state->next_time;
 | 
					 | 
				
			||||||
			/* TODO: check sequence? reordering? packet loss? */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (delta > state->sample_cnt) {
 | 
					 | 
				
			||||||
				/* There is a time gap between the last packet
 | 
					 | 
				
			||||||
				 * and the current one. Just discard the
 | 
					 | 
				
			||||||
				 * partial data that is left in the buffer.
 | 
					 | 
				
			||||||
				 * TODO: This can be improved by adding silence
 | 
					 | 
				
			||||||
				 * instead if the delta is small enough.
 | 
					 | 
				
			||||||
				 */
 | 
					 | 
				
			||||||
				LOGP(DLMGCP, LOGL_NOTICE,
 | 
					 | 
				
			||||||
					"0x%x dropping sample buffer due delta=%d sample_cnt=%zu\n",
 | 
					 | 
				
			||||||
					ENDPOINT_NUMBER(endp), delta, state->sample_cnt);
 | 
					 | 
				
			||||||
				state->sample_cnt = 0;
 | 
					 | 
				
			||||||
				state->next_time = ts_no;
 | 
					 | 
				
			||||||
			} else if (delta < 0) {
 | 
					 | 
				
			||||||
				LOGP(DLMGCP, LOGL_NOTICE,
 | 
					 | 
				
			||||||
				     "RTP time jumps backwards, delta = %d, "
 | 
					 | 
				
			||||||
				     "discarding buffered samples\n",
 | 
					 | 
				
			||||||
				     delta);
 | 
					 | 
				
			||||||
				state->sample_cnt = 0;
 | 
					 | 
				
			||||||
				state->sample_offs = 0;
 | 
					 | 
				
			||||||
				return -EAGAIN;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			/* Make sure the samples start without offset */
 | 
					 | 
				
			||||||
			if (state->sample_offs && state->sample_cnt)
 | 
					 | 
				
			||||||
				memmove(&state->samples[0],
 | 
					 | 
				
			||||||
					&state->samples[state->sample_offs],
 | 
					 | 
				
			||||||
					state->sample_cnt *
 | 
					 | 
				
			||||||
					sizeof(state->samples[0]));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		state->sample_offs = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* Append decoded audio to samples */
 | 
					 | 
				
			||||||
		decode_audio(state, &src, &nbytes);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (nbytes > 0)
 | 
					 | 
				
			||||||
			LOGP(DLMGCP, LOGL_NOTICE,
 | 
					 | 
				
			||||||
			     "Skipped audio frame in RTP packet: %zu octets\n",
 | 
					 | 
				
			||||||
			     nbytes);
 | 
					 | 
				
			||||||
	} else
 | 
					 | 
				
			||||||
		ts_no = state->next_time;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (state->sample_cnt < state->dst_packet_duration)
 | 
					 | 
				
			||||||
		return -EAGAIN;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	max_samples =
 | 
					 | 
				
			||||||
		state->dst_packet_duration ?
 | 
					 | 
				
			||||||
		state->dst_packet_duration : state->sample_cnt;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	nsamples = state->sample_cnt;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	rc = encode_audio(state, dst, buf_size, max_samples);
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * There were no samples to encode?
 | 
					 | 
				
			||||||
	 * TODO: how does this work for comfort noise?
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	if (rc == 0)
 | 
					 | 
				
			||||||
		return -ENOMSG;
 | 
					 | 
				
			||||||
	/* Any other error during the encoding */
 | 
					 | 
				
			||||||
	if (rc < 0)
 | 
					 | 
				
			||||||
		return rc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	nsamples -= state->sample_cnt;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	*len = rtp_hdr_size + rc;
 | 
					 | 
				
			||||||
	rtp_hdr->sequence = htons(state->next_seq);
 | 
					 | 
				
			||||||
	rtp_hdr->timestamp = htonl(ts_no);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	state->next_seq += 1;
 | 
					 | 
				
			||||||
	state->next_time = ts_no + nsamples;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * XXX: At this point we should always have consumed
 | 
					 | 
				
			||||||
	 * samples. So doing OSMO_ASSERT(nsamples > 0) and returning
 | 
					 | 
				
			||||||
	 * rtp_hdr_size should be fine.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	return nsamples ? rtp_hdr_size : 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -9,6 +9,7 @@ AM_CFLAGS = \
 | 
				
			|||||||
	-Wall \
 | 
						-Wall \
 | 
				
			||||||
	$(LIBOSMOCORE_CFLAGS) \
 | 
						$(LIBOSMOCORE_CFLAGS) \
 | 
				
			||||||
	$(LIBOSMOVTY_CFLAGS) \
 | 
						$(LIBOSMOVTY_CFLAGS) \
 | 
				
			||||||
 | 
						$(LIBOSMOABIS_CFLAGS) \
 | 
				
			||||||
	$(COVERAGE_CFLAGS) \
 | 
						$(COVERAGE_CFLAGS) \
 | 
				
			||||||
	$(NULL)
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -20,7 +21,7 @@ AM_LDFLAGS = \
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# This is not at all related to the release version, but a range of supported
 | 
					# This is not at all related to the release version, but a range of supported
 | 
				
			||||||
# API versions. Read TODO_RELEASE in the source tree's root!
 | 
					# API versions. Read TODO_RELEASE in the source tree's root!
 | 
				
			||||||
MGCP_CLIENT_LIBVERSION=2:0:0
 | 
					MGCP_CLIENT_LIBVERSION=9:0:0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
lib_LTLIBRARIES = \
 | 
					lib_LTLIBRARIES = \
 | 
				
			||||||
	libosmo-mgcp-client.la \
 | 
						libosmo-mgcp-client.la \
 | 
				
			||||||
@@ -29,6 +30,9 @@ lib_LTLIBRARIES = \
 | 
				
			|||||||
libosmo_mgcp_client_la_SOURCES = \
 | 
					libosmo_mgcp_client_la_SOURCES = \
 | 
				
			||||||
	mgcp_client.c \
 | 
						mgcp_client.c \
 | 
				
			||||||
	mgcp_client_vty.c \
 | 
						mgcp_client_vty.c \
 | 
				
			||||||
 | 
						mgcp_client_fsm.c \
 | 
				
			||||||
 | 
						mgcp_client_endpoint_fsm.c \
 | 
				
			||||||
 | 
						mgcp_client_pool.c \
 | 
				
			||||||
	$(NULL)
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
libosmo_mgcp_client_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(MGCP_CLIENT_LIBVERSION)
 | 
					libosmo_mgcp_client_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(MGCP_CLIENT_LIBVERSION)
 | 
				
			||||||
 
 | 
				
			|||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1036
									
								
								src/libosmo-mgcp-client/mgcp_client_endpoint_fsm.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1036
									
								
								src/libosmo-mgcp-client/mgcp_client_endpoint_fsm.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										766
									
								
								src/libosmo-mgcp-client/mgcp_client_fsm.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										766
									
								
								src/libosmo-mgcp-client/mgcp_client_fsm.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,766 @@
 | 
				
			|||||||
 | 
					/* (C) 2018 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Author: Philipp Maier
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/mgcp_client/mgcp_client.h>
 | 
				
			||||||
 | 
					#include <osmocom/mgcp_client/mgcp_client_fsm.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/utils.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/fsm.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/byteswap.h>
 | 
				
			||||||
 | 
					#include <arpa/inet.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/logging.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/sockaddr_str.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Context information, this is attached to the priv pointer of the FSM and
 | 
				
			||||||
 | 
					 * is also handed back when dispatcheing events to the parent FSM. This is
 | 
				
			||||||
 | 
					 * purly intened and not meant to be accessible for the API user */
 | 
				
			||||||
 | 
					struct mgcp_ctx {
 | 
				
			||||||
 | 
						/* MGCP client instance that is used to interact with the MGW */
 | 
				
			||||||
 | 
						struct mgcp_client *mgcp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* The ID of the last pending transaction. This is used internally
 | 
				
			||||||
 | 
						 * to cancel the transaction in case of an error */
 | 
				
			||||||
 | 
						mgcp_trans_id_t mgw_pending_trans;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Flag to mark that there is a pending transaction */
 | 
				
			||||||
 | 
						bool mgw_trans_pending;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Connection ID which has been assigned by he MGW */
 | 
				
			||||||
 | 
						char conn_id[MGCP_CONN_ID_MAXLEN];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Local RTP connection info, the MGW will send outgoing traffic to the
 | 
				
			||||||
 | 
						 * ip/port specified here. The Address does not have to be choosen right
 | 
				
			||||||
 | 
						 * on the creation of a connection. It can always be modified later by
 | 
				
			||||||
 | 
						 * the user. */
 | 
				
			||||||
 | 
						struct mgcp_conn_peer conn_peer_local;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Remote RTP connection info, the ip/port specified here is the address
 | 
				
			||||||
 | 
						 * where the MGW expects the RTP data to be sent. This address is
 | 
				
			||||||
 | 
						 * defined by soly by the MGW and can not be influenced by the user. */
 | 
				
			||||||
 | 
						struct mgcp_conn_peer conn_peer_remote;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* The terminate flag is a way to handle cornercase sitations that
 | 
				
			||||||
 | 
						 * might occur when the user runs into an error situation and sends
 | 
				
			||||||
 | 
						 * a DLCX command while the FSM is waiting for a response. In this
 | 
				
			||||||
 | 
						 * case the DLCX command is not executed immediately. Instead the
 | 
				
			||||||
 | 
						 * terminate flag is set. When the response to from the previous
 | 
				
			||||||
 | 
						 * operation is received, we know that there is a DLCX event is
 | 
				
			||||||
 | 
						 * pending. The FSM then generates the EV_DLCX by itsself before
 | 
				
			||||||
 | 
						 * it enters ST_READY to cause the immediate execution of the
 | 
				
			||||||
 | 
						 * DLCX procedure. (If normal operations are executed too fast,
 | 
				
			||||||
 | 
						 * the API functions will return an error. In general, the user
 | 
				
			||||||
 | 
						 * should synchronize using the callback events) */
 | 
				
			||||||
 | 
						bool terminate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Event that is sent when the current operation is completed (except
 | 
				
			||||||
 | 
						 * for DLCX, there the specified parent_term_evt is sent instead) */
 | 
				
			||||||
 | 
						uint32_t parent_evt;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define S(x)	(1 << (x))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MGCP_MGW_TIMEOUT 4	/* in seconds */
 | 
				
			||||||
 | 
					#define MGCP_MGW_TIMEOUT_TIMER_NR 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum fsm_mgcp_client_states {
 | 
				
			||||||
 | 
						ST_CRCX,
 | 
				
			||||||
 | 
						ST_CRCX_RESP,
 | 
				
			||||||
 | 
						ST_READY,
 | 
				
			||||||
 | 
						ST_MDCX_RESP,
 | 
				
			||||||
 | 
						ST_DLCX_RESP,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum fsm_mgcp_client_evt {
 | 
				
			||||||
 | 
						EV_CRCX,
 | 
				
			||||||
 | 
						EV_CRCX_RESP,
 | 
				
			||||||
 | 
						EV_MDCX,
 | 
				
			||||||
 | 
						EV_MDCX_RESP,
 | 
				
			||||||
 | 
						EV_DLCX,
 | 
				
			||||||
 | 
						EV_DLCX_RESP,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct value_string fsm_mgcp_client_evt_names[] = {
 | 
				
			||||||
 | 
						OSMO_VALUE_STRING(EV_CRCX),
 | 
				
			||||||
 | 
						OSMO_VALUE_STRING(EV_CRCX_RESP),
 | 
				
			||||||
 | 
						OSMO_VALUE_STRING(EV_MDCX),
 | 
				
			||||||
 | 
						OSMO_VALUE_STRING(EV_MDCX_RESP),
 | 
				
			||||||
 | 
						OSMO_VALUE_STRING(EV_DLCX),
 | 
				
			||||||
 | 
						OSMO_VALUE_STRING(EV_DLCX_RESP),
 | 
				
			||||||
 | 
						{0, NULL}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void make_crcx_msg(struct mgcp_msg *mgcp_msg, struct mgcp_conn_peer *info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						*mgcp_msg = (struct mgcp_msg) {
 | 
				
			||||||
 | 
							.verb = MGCP_VERB_CRCX,
 | 
				
			||||||
 | 
							.presence = (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID
 | 
				
			||||||
 | 
								     | MGCP_MSG_PRESENCE_CONN_MODE),
 | 
				
			||||||
 | 
							.call_id = info->call_id,
 | 
				
			||||||
 | 
							.conn_mode = MGCP_CONN_RECV_ONLY,
 | 
				
			||||||
 | 
							.ptime = info->ptime,
 | 
				
			||||||
 | 
							.codecs_len = info->codecs_len,
 | 
				
			||||||
 | 
							.ptmap_len = info->ptmap_len,
 | 
				
			||||||
 | 
							.param_present = info->param_present
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						osmo_strlcpy(mgcp_msg->endpoint, info->endpoint, MGCP_ENDPOINT_MAXLEN);
 | 
				
			||||||
 | 
						memcpy(mgcp_msg->codecs, info->codecs, sizeof(mgcp_msg->codecs));
 | 
				
			||||||
 | 
						memcpy(mgcp_msg->ptmap, info->ptmap, sizeof(mgcp_msg->ptmap));
 | 
				
			||||||
 | 
						memcpy(&mgcp_msg->param, &info->param, sizeof(mgcp_msg->param));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (info->x_osmo_ign) {
 | 
				
			||||||
 | 
							mgcp_msg->x_osmo_ign = info->x_osmo_ign;
 | 
				
			||||||
 | 
							mgcp_msg->presence |= MGCP_MSG_PRESENCE_X_OSMO_IGN;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (info->x_osmo_osmux_use) {
 | 
				
			||||||
 | 
							mgcp_msg->x_osmo_osmux_cid = info->x_osmo_osmux_cid;
 | 
				
			||||||
 | 
							mgcp_msg->presence |= MGCP_MSG_PRESENCE_X_OSMO_OSMUX_CID;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void add_audio(struct mgcp_msg *mgcp_msg, struct mgcp_conn_peer *info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						mgcp_msg->presence |= MGCP_MSG_PRESENCE_AUDIO_IP | MGCP_MSG_PRESENCE_AUDIO_PORT;
 | 
				
			||||||
 | 
						mgcp_msg->audio_ip = info->addr;
 | 
				
			||||||
 | 
						mgcp_msg->audio_port = info->port;
 | 
				
			||||||
 | 
						mgcp_msg->conn_mode = MGCP_CONN_RECV_SEND;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void set_conn_mode(struct mgcp_msg *mgcp_msg, struct mgcp_conn_peer *peer)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						enum mgcp_connection_mode conn_mode = peer->conn_mode;
 | 
				
			||||||
 | 
						if (conn_mode != MGCP_CONN_NONE)
 | 
				
			||||||
 | 
							mgcp_msg->conn_mode = conn_mode;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct msgb *make_mdcx_msg(struct mgcp_ctx *mgcp_ctx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mgcp_msg mgcp_msg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mgcp_msg = (struct mgcp_msg) {
 | 
				
			||||||
 | 
							.verb = MGCP_VERB_MDCX,
 | 
				
			||||||
 | 
							.presence = (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID | MGCP_MSG_PRESENCE_CONN_ID |
 | 
				
			||||||
 | 
								     MGCP_MSG_PRESENCE_CONN_MODE | MGCP_MSG_PRESENCE_AUDIO_IP | MGCP_MSG_PRESENCE_AUDIO_PORT),
 | 
				
			||||||
 | 
							.call_id =  mgcp_ctx->conn_peer_remote.call_id,
 | 
				
			||||||
 | 
							.conn_id = mgcp_ctx->conn_id,
 | 
				
			||||||
 | 
							.conn_mode = MGCP_CONN_RECV_SEND,
 | 
				
			||||||
 | 
							.audio_ip = mgcp_ctx->conn_peer_local.addr,
 | 
				
			||||||
 | 
							.audio_port = mgcp_ctx->conn_peer_local.port,
 | 
				
			||||||
 | 
							.ptime = mgcp_ctx->conn_peer_local.ptime,
 | 
				
			||||||
 | 
							.codecs_len = mgcp_ctx->conn_peer_local.codecs_len,
 | 
				
			||||||
 | 
							.ptmap_len = mgcp_ctx->conn_peer_local.ptmap_len,
 | 
				
			||||||
 | 
							.param_present = mgcp_ctx->conn_peer_local.param_present
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						osmo_strlcpy(mgcp_msg.endpoint, mgcp_ctx->conn_peer_remote.endpoint, MGCP_ENDPOINT_MAXLEN);
 | 
				
			||||||
 | 
						memcpy(mgcp_msg.codecs, mgcp_ctx->conn_peer_local.codecs, sizeof(mgcp_msg.codecs));
 | 
				
			||||||
 | 
						memcpy(mgcp_msg.ptmap, mgcp_ctx->conn_peer_local.ptmap, sizeof(mgcp_msg.ptmap));
 | 
				
			||||||
 | 
						memcpy(&mgcp_msg.param, &mgcp_ctx->conn_peer_local.param, sizeof(mgcp_ctx->conn_peer_local.param));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						set_conn_mode(&mgcp_msg, &mgcp_ctx->conn_peer_local);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (mgcp_ctx->conn_peer_local.x_osmo_osmux_use) {
 | 
				
			||||||
 | 
							mgcp_msg.x_osmo_osmux_cid = mgcp_ctx->conn_peer_local.x_osmo_osmux_cid;
 | 
				
			||||||
 | 
							mgcp_msg.presence |= MGCP_MSG_PRESENCE_X_OSMO_OSMUX_CID;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Note: We take the endpoint and the call_id from the remote
 | 
				
			||||||
 | 
						 * connection info, because we can be confident that the
 | 
				
			||||||
 | 
						 * information there is valid. For the local info, we explicitly
 | 
				
			||||||
 | 
						 * allow endpoint and call_id to be optional */
 | 
				
			||||||
 | 
						return mgcp_msg_gen(mgcp_ctx->mgcp, &mgcp_msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct msgb *make_dlcx_msg(struct mgcp_ctx *mgcp_ctx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mgcp_msg mgcp_msg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mgcp_msg = (struct mgcp_msg) {
 | 
				
			||||||
 | 
							.verb = MGCP_VERB_DLCX,
 | 
				
			||||||
 | 
							.presence = (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID | MGCP_MSG_PRESENCE_CONN_ID),
 | 
				
			||||||
 | 
							.call_id = mgcp_ctx->conn_peer_remote.call_id,
 | 
				
			||||||
 | 
							.conn_id = mgcp_ctx->conn_id,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						osmo_strlcpy(mgcp_msg.endpoint, mgcp_ctx->conn_peer_remote.endpoint, MGCP_ENDPOINT_MAXLEN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return mgcp_msg_gen(mgcp_ctx->mgcp, &mgcp_msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void mgw_crcx_resp_cb(struct mgcp_response *r, void *priv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void fsm_crcx_cb(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mgcp_ctx *mgcp_ctx = data;
 | 
				
			||||||
 | 
						struct mgcp_client *mgcp;
 | 
				
			||||||
 | 
						struct mgcp_msg mgcp_msg;
 | 
				
			||||||
 | 
						struct msgb *msg;
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						OSMO_ASSERT(mgcp_ctx);
 | 
				
			||||||
 | 
						mgcp = mgcp_ctx->mgcp;
 | 
				
			||||||
 | 
						OSMO_ASSERT(mgcp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (event) {
 | 
				
			||||||
 | 
						case EV_CRCX:
 | 
				
			||||||
 | 
							LOGPFSML(fi, LOGL_DEBUG, "MGW/CRCX: creating connection on MGW endpoint:%s...\n",
 | 
				
			||||||
 | 
								 mgcp_ctx->conn_peer_local.endpoint);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							make_crcx_msg(&mgcp_msg, &mgcp_ctx->conn_peer_local);
 | 
				
			||||||
 | 
							if (mgcp_ctx->conn_peer_local.port)
 | 
				
			||||||
 | 
								add_audio(&mgcp_msg, &mgcp_ctx->conn_peer_local);
 | 
				
			||||||
 | 
							set_conn_mode(&mgcp_msg, &mgcp_ctx->conn_peer_local);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							msg = mgcp_msg_gen(mgcp_ctx->mgcp, &mgcp_msg);
 | 
				
			||||||
 | 
							OSMO_ASSERT(msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							mgcp_ctx->mgw_pending_trans = mgcp_msg_trans_id(msg);
 | 
				
			||||||
 | 
							mgcp_ctx->mgw_trans_pending = true;
 | 
				
			||||||
 | 
							rc = mgcp_client_tx(mgcp, msg, mgw_crcx_resp_cb, fi);
 | 
				
			||||||
 | 
							if (rc < 0) {
 | 
				
			||||||
 | 
								osmo_fsm_inst_term(fi, OSMO_FSM_TERM_ERROR, NULL);
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							osmo_fsm_inst_state_chg(fi, ST_CRCX_RESP, MGCP_MGW_TIMEOUT, MGCP_MGW_TIMEOUT_TIMER_NR);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							OSMO_ASSERT(false);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Return the CI that the MGW allocated during CRCX response. This is purely informational for logging
 | 
				
			||||||
 | 
					 * and identity tracking; the mgcp_conn_*() functions take care of using the right CI internally. */
 | 
				
			||||||
 | 
					const char *mgcp_conn_get_ci(struct osmo_fsm_inst *fi)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mgcp_ctx *mgcp_ctx = fi->priv;
 | 
				
			||||||
 | 
						return mgcp_ctx->conn_id;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Get the mgcp_client that is used with this mgcp_client_fsm instance */
 | 
				
			||||||
 | 
					struct mgcp_client *mgcp_conn_get_client(struct osmo_fsm_inst *fi)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mgcp_ctx *mgcp_ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!fi)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mgcp_ctx = fi->priv;
 | 
				
			||||||
 | 
						return mgcp_ctx->mgcp;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void mgw_crcx_resp_cb(struct mgcp_response *r, void *priv)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct osmo_fsm_inst *fi = priv;
 | 
				
			||||||
 | 
						struct mgcp_ctx *mgcp_ctx;
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						OSMO_ASSERT(fi);
 | 
				
			||||||
 | 
						mgcp_ctx = fi->priv;
 | 
				
			||||||
 | 
						OSMO_ASSERT(mgcp_ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mgcp_ctx->mgw_trans_pending = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (r->head.response_code != 200) {
 | 
				
			||||||
 | 
							LOGPFSML(fi, LOGL_ERROR,
 | 
				
			||||||
 | 
								 "MGW/CRCX: response yields error: %d %s\n", r->head.response_code, r->head.comment);
 | 
				
			||||||
 | 
							osmo_fsm_inst_term(fi, OSMO_FSM_TERM_ERROR, NULL);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						osmo_strlcpy(mgcp_ctx->conn_id, r->head.conn_id, sizeof(mgcp_ctx->conn_id));
 | 
				
			||||||
 | 
						LOGPFSML(fi, LOGL_DEBUG, "MGW/CRCX: MGW responded with CI: %s\n", mgcp_ctx->conn_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc = mgcp_response_parse_params(r);
 | 
				
			||||||
 | 
						if (rc) {
 | 
				
			||||||
 | 
							LOGPFSML(fi, LOGL_ERROR, "MGW/CRCX: Cannot parse CRCX response\n");
 | 
				
			||||||
 | 
							osmo_fsm_inst_term(fi, OSMO_FSM_TERM_ERROR, NULL);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						LOGPFSML(fi, LOGL_DEBUG, "MGW/CRCX: MGW responded with address %s:%u\n", r->audio_ip, r->audio_port);
 | 
				
			||||||
 | 
						if (r->head.x_osmo_osmux_use) {
 | 
				
			||||||
 | 
							LOGPFSML(fi, LOGL_DEBUG, "MGW/CRCX: MGW responded using Osmux %u\n", r->head.x_osmo_osmux_cid);
 | 
				
			||||||
 | 
							mgcp_ctx->conn_peer_remote.x_osmo_osmux_use = true;
 | 
				
			||||||
 | 
							mgcp_ctx->conn_peer_remote.x_osmo_osmux_cid = r->head.x_osmo_osmux_cid;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						osmo_strlcpy(mgcp_ctx->conn_peer_remote.addr, r->audio_ip, sizeof(mgcp_ctx->conn_peer_remote.addr));
 | 
				
			||||||
 | 
						mgcp_ctx->conn_peer_remote.port = r->audio_port;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (strlen(r->head.endpoint) > 0) {
 | 
				
			||||||
 | 
							/* If we get an endpoint identifier back from the MGW, take it */
 | 
				
			||||||
 | 
							osmo_strlcpy(mgcp_ctx->conn_peer_remote.endpoint, r->head.endpoint,
 | 
				
			||||||
 | 
								     sizeof(mgcp_ctx->conn_peer_remote.endpoint));
 | 
				
			||||||
 | 
						} else if (strstr(mgcp_ctx->conn_peer_local.endpoint, "*") == NULL) {
 | 
				
			||||||
 | 
							/* If we do not get an endpoint identifier back and the
 | 
				
			||||||
 | 
							 * identifier we used to create the connection is not a
 | 
				
			||||||
 | 
							 * wildcarded one, we take the local endpoint identifier
 | 
				
			||||||
 | 
							 * instead */
 | 
				
			||||||
 | 
							osmo_strlcpy(mgcp_ctx->conn_peer_remote.endpoint, mgcp_ctx->conn_peer_local.endpoint,
 | 
				
			||||||
 | 
								     sizeof(mgcp_ctx->conn_peer_local.endpoint));
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							LOGPFSML(fi, LOGL_ERROR, "MGW/CRCX: CRCX yielded not suitable endpoint identifier\n");
 | 
				
			||||||
 | 
							osmo_fsm_inst_term(fi, OSMO_FSM_TERM_ERROR, NULL);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mgcp_ctx->conn_peer_remote.call_id = mgcp_ctx->conn_peer_local.call_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						osmo_fsm_inst_dispatch(fi, EV_CRCX_RESP, mgcp_ctx);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void fsm_crcx_resp_cb(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mgcp_ctx *mgcp_ctx = data;
 | 
				
			||||||
 | 
						OSMO_ASSERT(mgcp_ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (event) {
 | 
				
			||||||
 | 
						case EV_CRCX_RESP:
 | 
				
			||||||
 | 
							osmo_fsm_inst_state_chg(fi, ST_READY, 0, 0);
 | 
				
			||||||
 | 
							if (mgcp_ctx->terminate) {
 | 
				
			||||||
 | 
								/* Trigger immediate DLCX if DLCX was requested while the FSM was
 | 
				
			||||||
 | 
								 * busy with the previous operation */
 | 
				
			||||||
 | 
								LOGPFSML(fi, LOGL_ERROR, "MGW/CRCX: FSM was busy while DLCX was requested, executing now...\n");
 | 
				
			||||||
 | 
								osmo_fsm_inst_dispatch(fi, EV_DLCX, mgcp_ctx);
 | 
				
			||||||
 | 
							} else
 | 
				
			||||||
 | 
								osmo_fsm_inst_dispatch(fi->proc.parent, mgcp_ctx->parent_evt, &mgcp_ctx->conn_peer_remote);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							OSMO_ASSERT(false);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void mgw_mdcx_resp_cb(struct mgcp_response *r, void *priv);
 | 
				
			||||||
 | 
					static void mgw_dlcx_resp_cb(struct mgcp_response *r, void *priv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void fsm_ready_cb(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mgcp_ctx *mgcp_ctx = data;
 | 
				
			||||||
 | 
						struct msgb *msg;
 | 
				
			||||||
 | 
						struct mgcp_client *mgcp;
 | 
				
			||||||
 | 
						uint32_t new_state;
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						OSMO_ASSERT(mgcp_ctx);
 | 
				
			||||||
 | 
						mgcp = mgcp_ctx->mgcp;
 | 
				
			||||||
 | 
						OSMO_ASSERT(mgcp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (event) {
 | 
				
			||||||
 | 
						case EV_MDCX:
 | 
				
			||||||
 | 
							msg = make_mdcx_msg(mgcp_ctx);
 | 
				
			||||||
 | 
							OSMO_ASSERT(msg);
 | 
				
			||||||
 | 
							rc = mgcp_client_tx(mgcp, msg, mgw_mdcx_resp_cb, fi);
 | 
				
			||||||
 | 
							new_state = ST_MDCX_RESP;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case EV_DLCX:
 | 
				
			||||||
 | 
							msg = make_dlcx_msg(mgcp_ctx);
 | 
				
			||||||
 | 
							OSMO_ASSERT(msg);
 | 
				
			||||||
 | 
							rc = mgcp_client_tx(mgcp, msg, mgw_dlcx_resp_cb, fi);
 | 
				
			||||||
 | 
							new_state = ST_DLCX_RESP;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							OSMO_ASSERT(false);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mgcp_ctx->mgw_pending_trans = mgcp_msg_trans_id(msg);
 | 
				
			||||||
 | 
						mgcp_ctx->mgw_trans_pending = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (rc < 0) {
 | 
				
			||||||
 | 
							osmo_fsm_inst_term(fi, OSMO_FSM_TERM_ERROR, NULL);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						osmo_fsm_inst_state_chg(fi, new_state, MGCP_MGW_TIMEOUT, MGCP_MGW_TIMEOUT_TIMER_NR);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void mgw_mdcx_resp_cb(struct mgcp_response *r, void *priv)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct osmo_fsm_inst *fi = priv;
 | 
				
			||||||
 | 
						struct mgcp_ctx *mgcp_ctx;
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						OSMO_ASSERT(fi);
 | 
				
			||||||
 | 
						mgcp_ctx = fi->priv;
 | 
				
			||||||
 | 
						OSMO_ASSERT(mgcp_ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mgcp_ctx->mgw_trans_pending = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (r->head.response_code != 200) {
 | 
				
			||||||
 | 
							LOGPFSML(fi, LOGL_ERROR, "MGW/MDCX: response yields error: %d %s\n", r->head.response_code,
 | 
				
			||||||
 | 
								 r->head.comment);
 | 
				
			||||||
 | 
							osmo_fsm_inst_term(fi, OSMO_FSM_TERM_ERROR, NULL);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc = mgcp_response_parse_params(r);
 | 
				
			||||||
 | 
						if (rc) {
 | 
				
			||||||
 | 
							LOGPFSML(fi, LOGL_ERROR, "MGW/MDCX: Cannot parse MDCX response\n");
 | 
				
			||||||
 | 
							osmo_fsm_inst_term(fi, OSMO_FSM_TERM_ERROR, NULL);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						LOGPFSML(fi, LOGL_DEBUG, "MGW/MDCX: MGW responded with address %s:%u\n", r->audio_ip, r->audio_port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (r->head.x_osmo_osmux_use) {
 | 
				
			||||||
 | 
							LOGPFSML(fi, LOGL_DEBUG, "MGW/CRCX: MGW responded using Osmux %u\n", r->head.x_osmo_osmux_cid);
 | 
				
			||||||
 | 
							mgcp_ctx->conn_peer_remote.x_osmo_osmux_use = true;
 | 
				
			||||||
 | 
							mgcp_ctx->conn_peer_remote.x_osmo_osmux_cid = r->head.x_osmo_osmux_cid;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						osmo_strlcpy(mgcp_ctx->conn_peer_remote.addr, r->audio_ip, sizeof(mgcp_ctx->conn_peer_remote.addr));
 | 
				
			||||||
 | 
						mgcp_ctx->conn_peer_remote.port = r->audio_port;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						osmo_fsm_inst_dispatch(fi, EV_MDCX_RESP, mgcp_ctx);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void fsm_mdcx_resp_cb(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mgcp_ctx *mgcp_ctx = data;
 | 
				
			||||||
 | 
						OSMO_ASSERT(mgcp_ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (event) {
 | 
				
			||||||
 | 
						case EV_MDCX_RESP:
 | 
				
			||||||
 | 
							osmo_fsm_inst_state_chg(fi, ST_READY, 0, 0);
 | 
				
			||||||
 | 
							if (mgcp_ctx->terminate) {
 | 
				
			||||||
 | 
								/* Trigger immediate DLCX if DLCX was requested while the FSM was
 | 
				
			||||||
 | 
								 * busy with the previous operation */
 | 
				
			||||||
 | 
								LOGPFSML(fi, LOGL_ERROR, "MGW/MDCX: FSM was busy while DLCX was requested, executing now...\n");
 | 
				
			||||||
 | 
								osmo_fsm_inst_dispatch(fi, EV_DLCX, mgcp_ctx);
 | 
				
			||||||
 | 
							} else
 | 
				
			||||||
 | 
								osmo_fsm_inst_dispatch(fi->proc.parent, mgcp_ctx->parent_evt, &mgcp_ctx->conn_peer_remote);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							OSMO_ASSERT(false);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void mgw_dlcx_resp_cb(struct mgcp_response *r, void *priv)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct osmo_fsm_inst *fi = priv;
 | 
				
			||||||
 | 
						struct mgcp_ctx *mgcp_ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						OSMO_ASSERT(fi);
 | 
				
			||||||
 | 
						mgcp_ctx = fi->priv;
 | 
				
			||||||
 | 
						OSMO_ASSERT(mgcp_ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mgcp_ctx->mgw_trans_pending = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (r->head.response_code != 250) {
 | 
				
			||||||
 | 
							LOGPFSML(fi, LOGL_ERROR,
 | 
				
			||||||
 | 
								 "MGW/DLCX: response yields error: %d %s\n", r->head.response_code, r->head.comment);
 | 
				
			||||||
 | 
							osmo_fsm_inst_term(fi, OSMO_FSM_TERM_ERROR, NULL);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						osmo_fsm_inst_dispatch(fi, EV_DLCX_RESP, mgcp_ctx);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void fsm_dlcx_resp_cb(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mgcp_ctx *mgcp_ctx = data;
 | 
				
			||||||
 | 
						OSMO_ASSERT(mgcp_ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (event) {
 | 
				
			||||||
 | 
						case EV_DLCX_RESP:
 | 
				
			||||||
 | 
							/* Rub out the connection identifier, since the connection
 | 
				
			||||||
 | 
							 * is no longer present and we will use the connection id
 | 
				
			||||||
 | 
							 * to know in error cases if the connection is still present
 | 
				
			||||||
 | 
							 * or not */
 | 
				
			||||||
 | 
							memset(mgcp_ctx->conn_id, 0, sizeof(mgcp_ctx->conn_id));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							OSMO_ASSERT(false);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int fsm_timeout_cb(struct osmo_fsm_inst *fi)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mgcp_ctx *mgcp_ctx = fi->priv;
 | 
				
			||||||
 | 
						struct mgcp_client *mgcp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						OSMO_ASSERT(mgcp_ctx);
 | 
				
			||||||
 | 
						mgcp = mgcp_ctx->mgcp;
 | 
				
			||||||
 | 
						OSMO_ASSERT(mgcp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (fi->T == MGCP_MGW_TIMEOUT_TIMER_NR) {
 | 
				
			||||||
 | 
							/* Note: We were unable to communicate with the MGW,
 | 
				
			||||||
 | 
							 * unfortunately there is no meaningful action we can take
 | 
				
			||||||
 | 
							 * now other than giving up. */
 | 
				
			||||||
 | 
							osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							/* Note: Ther must not be any unsolicited timers
 | 
				
			||||||
 | 
							 * in this FSM. If so, we have serious problem. */
 | 
				
			||||||
 | 
							OSMO_ASSERT(false);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void fsm_cleanup_cb(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mgcp_ctx *mgcp_ctx = fi->priv;
 | 
				
			||||||
 | 
						struct mgcp_client *mgcp;
 | 
				
			||||||
 | 
						struct msgb *msg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						OSMO_ASSERT(mgcp_ctx);
 | 
				
			||||||
 | 
						mgcp = mgcp_ctx->mgcp;
 | 
				
			||||||
 | 
						OSMO_ASSERT(mgcp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* If there is still a transaction pending, cancel it now. */
 | 
				
			||||||
 | 
						if (mgcp_ctx->mgw_trans_pending)
 | 
				
			||||||
 | 
							mgcp_client_cancel(mgcp, mgcp_ctx->mgw_pending_trans);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Should the FSM be terminated while there are still open connections
 | 
				
			||||||
 | 
						 * on the MGW, we send an unconditional DLCX to terminate the
 | 
				
			||||||
 | 
						 * connection. This is not the normal case. The user should always use
 | 
				
			||||||
 | 
						 * mgcp_conn_delete() to instruct the FSM to perform a graceful exit.
 | 
				
			||||||
 | 
						 * If in ST_DLCX_RESP, a DLCX was already sent and we did not get a
 | 
				
			||||||
 | 
						 * response. No point in sending another one. */
 | 
				
			||||||
 | 
						if (fi->state != ST_DLCX_RESP && strlen(mgcp_ctx->conn_id)) {
 | 
				
			||||||
 | 
							LOGPFSML(fi, LOGL_INFO, "Conn cleanup, sending DLCX for %s %s\n", mgcp_ctx->conn_peer_remote.endpoint,
 | 
				
			||||||
 | 
								 mgcp_ctx->conn_id);
 | 
				
			||||||
 | 
							msg = make_dlcx_msg(mgcp_ctx);
 | 
				
			||||||
 | 
							if (!msg)
 | 
				
			||||||
 | 
								LOGPFSML(fi, LOGL_ERROR, "MGW/DLCX: Error composing DLCX message\n");
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								mgcp_client_tx(mgcp, msg, NULL, NULL);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						talloc_free(mgcp_ctx);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct osmo_fsm_state fsm_mgcp_client_states[] = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Initial CRCX state. This state is immediately entered and executed
 | 
				
			||||||
 | 
						 * when the FSM is started. The rationale is that we first have to
 | 
				
			||||||
 | 
						 * create a connectin before we can execute other operations on that
 | 
				
			||||||
 | 
						 * connection. */
 | 
				
			||||||
 | 
						[ST_CRCX] = {
 | 
				
			||||||
 | 
							     .in_event_mask = S(EV_CRCX),
 | 
				
			||||||
 | 
							     .out_state_mask = S(ST_CRCX_RESP),
 | 
				
			||||||
 | 
							     .name = OSMO_STRINGIFY(ST_CRCX),
 | 
				
			||||||
 | 
							     .action = fsm_crcx_cb,
 | 
				
			||||||
 | 
							     },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Wait for the response to a CRCX operation, check and process the
 | 
				
			||||||
 | 
						 * results, change to ST_READY afterwards. */
 | 
				
			||||||
 | 
						[ST_CRCX_RESP] = {
 | 
				
			||||||
 | 
								  .in_event_mask = S(EV_CRCX_RESP),
 | 
				
			||||||
 | 
								  .out_state_mask = S(ST_READY),
 | 
				
			||||||
 | 
								  .name = OSMO_STRINGIFY(ST_CRCX_RESP),
 | 
				
			||||||
 | 
								  .action = fsm_crcx_resp_cb,
 | 
				
			||||||
 | 
								  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* In this idle state we wait for further operations (e.g. MDCX) that
 | 
				
			||||||
 | 
						 * can be executed by the user using the API. There is no timeout in
 | 
				
			||||||
 | 
						 * this state. The connection lives on until the user decides to
 | 
				
			||||||
 | 
						 * terminate it (DLCX). */
 | 
				
			||||||
 | 
						[ST_READY] = {
 | 
				
			||||||
 | 
							      .in_event_mask = S(EV_MDCX) | S(EV_DLCX),
 | 
				
			||||||
 | 
							      .out_state_mask = S(ST_MDCX_RESP) | S(ST_DLCX_RESP),
 | 
				
			||||||
 | 
							      .name = OSMO_STRINGIFY(ST_READY),
 | 
				
			||||||
 | 
							      .action = fsm_ready_cb,
 | 
				
			||||||
 | 
							      },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Wait for the response of a MDCX operation, check and process the
 | 
				
			||||||
 | 
						 * results, change to ST_READY afterwards. */
 | 
				
			||||||
 | 
						[ST_MDCX_RESP] = {
 | 
				
			||||||
 | 
								  .in_event_mask = S(EV_MDCX_RESP),
 | 
				
			||||||
 | 
								  .out_state_mask = S(ST_READY),
 | 
				
			||||||
 | 
								  .name = OSMO_STRINGIFY(ST_MDCX_RESP),
 | 
				
			||||||
 | 
								  .action = fsm_mdcx_resp_cb,
 | 
				
			||||||
 | 
								  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Wait for the response of a DLCX operation and terminate the FSM
 | 
				
			||||||
 | 
						 * normally. */
 | 
				
			||||||
 | 
						[ST_DLCX_RESP] = {
 | 
				
			||||||
 | 
								  .in_event_mask = S(EV_DLCX_RESP),
 | 
				
			||||||
 | 
								  .out_state_mask = 0,
 | 
				
			||||||
 | 
								  .name = OSMO_STRINGIFY(ST_DLCX_RESP),
 | 
				
			||||||
 | 
								  .action = fsm_dlcx_resp_cb,
 | 
				
			||||||
 | 
								  },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct osmo_fsm fsm_mgcp_client = {
 | 
				
			||||||
 | 
						.name = "MGCP_CONN",
 | 
				
			||||||
 | 
						.states = fsm_mgcp_client_states,
 | 
				
			||||||
 | 
						.num_states = ARRAY_SIZE(fsm_mgcp_client_states),
 | 
				
			||||||
 | 
						.timer_cb = fsm_timeout_cb,
 | 
				
			||||||
 | 
						.cleanup = fsm_cleanup_cb,
 | 
				
			||||||
 | 
						.event_names = fsm_mgcp_client_evt_names,
 | 
				
			||||||
 | 
						.log_subsys = DLMGCP,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! allocate FSM, and create a new connection on the MGW.
 | 
				
			||||||
 | 
					 *  \param[in] mgcp MGCP client descriptor.
 | 
				
			||||||
 | 
					 *  \param[in] parent_fi Parent FSM instance.
 | 
				
			||||||
 | 
					 *  \param[in] parent_term_evt Event to be sent to parent when terminating.
 | 
				
			||||||
 | 
					 *  \param[in] parent_evt Event to be sent to parent when operation is done.
 | 
				
			||||||
 | 
					 *  \param[in] conn_peer Connection parameters (ip, port...).
 | 
				
			||||||
 | 
					 *  \returns newly-allocated, initialized and registered FSM instance, NULL on error. */
 | 
				
			||||||
 | 
					struct osmo_fsm_inst *mgcp_conn_create(struct mgcp_client *mgcp, struct osmo_fsm_inst *parent_fi,
 | 
				
			||||||
 | 
									       uint32_t parent_term_evt, uint32_t parent_evt, struct mgcp_conn_peer *conn_peer)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mgcp_ctx *mgcp_ctx;
 | 
				
			||||||
 | 
						struct osmo_fsm_inst *fi;
 | 
				
			||||||
 | 
						struct in6_addr ip_test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						OSMO_ASSERT(parent_fi);
 | 
				
			||||||
 | 
						OSMO_ASSERT(mgcp);
 | 
				
			||||||
 | 
						OSMO_ASSERT(conn_peer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Check if IP/Port information in conn info makes sense */
 | 
				
			||||||
 | 
						if (conn_peer->port && inet_pton(osmo_ip_str_type(conn_peer->addr),
 | 
				
			||||||
 | 
										 conn_peer->addr, &ip_test) != 1)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Allocate and configure a new fsm instance */
 | 
				
			||||||
 | 
						fi = osmo_fsm_inst_alloc_child(&fsm_mgcp_client, parent_fi, parent_term_evt);
 | 
				
			||||||
 | 
						OSMO_ASSERT(fi);
 | 
				
			||||||
 | 
						mgcp_ctx = talloc_zero(fi, struct mgcp_ctx);
 | 
				
			||||||
 | 
						OSMO_ASSERT(mgcp_ctx);
 | 
				
			||||||
 | 
						mgcp_ctx->mgcp = mgcp;
 | 
				
			||||||
 | 
						mgcp_ctx->parent_evt = parent_evt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memcpy(&mgcp_ctx->conn_peer_local, conn_peer, sizeof(mgcp_ctx->conn_peer_local));
 | 
				
			||||||
 | 
						fi->priv = mgcp_ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* start state machine */
 | 
				
			||||||
 | 
						OSMO_ASSERT(fi->state == ST_CRCX);
 | 
				
			||||||
 | 
						osmo_fsm_inst_dispatch(fi, EV_CRCX, mgcp_ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return fi;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! modify an existing connection on the MGW.
 | 
				
			||||||
 | 
					 *  \param[in] fi FSM instance.
 | 
				
			||||||
 | 
					 *  \param[in] parent_evt Event to be sent to parent when operation is done.
 | 
				
			||||||
 | 
					 *  \param[in] conn_peer New connection information (ip, port...).
 | 
				
			||||||
 | 
					 *  \returns 0 on success, -EINVAL on error. */
 | 
				
			||||||
 | 
					int mgcp_conn_modify(struct osmo_fsm_inst *fi, uint32_t parent_evt, struct mgcp_conn_peer *conn_peer)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						OSMO_ASSERT(fi);
 | 
				
			||||||
 | 
						struct mgcp_ctx *mgcp_ctx = fi->priv;
 | 
				
			||||||
 | 
						struct in6_addr ip_test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						OSMO_ASSERT(mgcp_ctx);
 | 
				
			||||||
 | 
						OSMO_ASSERT(conn_peer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* The user must not issue an MDCX before the CRCX has completed,
 | 
				
			||||||
 | 
						 * if this happens, it means that the parent FSM has overhead the
 | 
				
			||||||
 | 
						 * parent_evt (mandatory!) and executed the MDCX without even
 | 
				
			||||||
 | 
						 * waiting for the results. Another reason could be that the
 | 
				
			||||||
 | 
						 * parent FSM got messed up */
 | 
				
			||||||
 | 
						OSMO_ASSERT(fi->state != ST_CRCX_RESP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* If the user tries to issue an MDCX while an DLCX operation is
 | 
				
			||||||
 | 
						 * pending, there must be a serious problem with the paren FSM.
 | 
				
			||||||
 | 
						 * Eeither the parent_term_evt (mandatory!) has been overheard,
 | 
				
			||||||
 | 
						 * or the parant FSM got messed so badly that it still assumes
 | 
				
			||||||
 | 
						 * a live connection although it as killed it. */
 | 
				
			||||||
 | 
						OSMO_ASSERT(fi->state != ST_DLCX_RESP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Check if IP/Port parameters make sense */
 | 
				
			||||||
 | 
						if (conn_peer->port == 0) {
 | 
				
			||||||
 | 
							LOGPFSML(fi, LOGL_ERROR, "Cannot MDCX, port == 0\n");
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (inet_pton(osmo_ip_str_type(conn_peer->addr), conn_peer->addr, &ip_test) != 1) {
 | 
				
			||||||
 | 
							LOGPFSML(fi, LOGL_ERROR, "Cannot MDCX, IP address %s\n", conn_peer->addr);
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! The user may supply an endpoint identifier in conn_peer. The
 | 
				
			||||||
 | 
						 *  identifier is then checked. This check is optional. Later steps do
 | 
				
			||||||
 | 
						 *  not depend on the endpoint identifier supplied here because it is
 | 
				
			||||||
 | 
						 *  already implicitly known from the CRCX phase. */
 | 
				
			||||||
 | 
						if (strlen(conn_peer->endpoint) && strcmp(conn_peer->endpoint, mgcp_ctx->conn_peer_remote.endpoint)) {
 | 
				
			||||||
 | 
							LOGPFSML(fi, LOGL_ERROR, "Cannot MDCX, endpoint mismatches: requested %s, should be %s\n",
 | 
				
			||||||
 | 
								 conn_peer->endpoint, mgcp_ctx->conn_peer_remote.endpoint);
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! Note: The call-id is implicitly known from the previous CRCX and
 | 
				
			||||||
 | 
						 *  will not be checked even when it is set in conn_peer. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mgcp_ctx->parent_evt = parent_evt;
 | 
				
			||||||
 | 
						memcpy(&mgcp_ctx->conn_peer_local, conn_peer, sizeof(mgcp_ctx->conn_peer_local));
 | 
				
			||||||
 | 
						osmo_fsm_inst_dispatch(fi, EV_MDCX, mgcp_ctx);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! delete existing connection on the MGW, destroy FSM afterwards.
 | 
				
			||||||
 | 
					 *  \param[in] fi FSM instance. */
 | 
				
			||||||
 | 
					void mgcp_conn_delete(struct osmo_fsm_inst *fi)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						OSMO_ASSERT(fi);
 | 
				
			||||||
 | 
						struct mgcp_ctx *mgcp_ctx = fi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						OSMO_ASSERT(mgcp_ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (fi->proc.terminating)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Unlink FSM from parent, set the struct mgcp_client as new talloc ctx. */
 | 
				
			||||||
 | 
						osmo_fsm_inst_unlink_parent(fi, mgcp_ctx->mgcp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* An error situation where the parent FSM must be killed immediately
 | 
				
			||||||
 | 
						 * may lead into a situation where the DLCX can not be executed right
 | 
				
			||||||
 | 
						 * at that moment because the FSM is still busy with another operation.
 | 
				
			||||||
 | 
						 * In those cases we postpone the DLCX so that the FSM and the
 | 
				
			||||||
 | 
						 * connections on the MGW get cleaned up gracefully. */
 | 
				
			||||||
 | 
						if (fi->state != ST_READY) {
 | 
				
			||||||
 | 
							LOGPFSML(fi, LOGL_ERROR, "MGW: operation still pending, DLCX will be postponed.\n");
 | 
				
			||||||
 | 
							mgcp_ctx->terminate = true;
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						osmo_fsm_inst_dispatch(fi, EV_DLCX, mgcp_ctx);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *osmo_mgcpc_conn_peer_name(const struct mgcp_conn_peer *info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/* I'd be fine with a smaller buffer and accept truncation, but gcc possibly refuses to build if
 | 
				
			||||||
 | 
						 * this buffer is too small. */
 | 
				
			||||||
 | 
						static char buf[1024];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!info)
 | 
				
			||||||
 | 
							return "NULL";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (info->endpoint[0]
 | 
				
			||||||
 | 
						    && info->addr[0])
 | 
				
			||||||
 | 
							snprintf(buf, sizeof(buf), "%s:%s:%u",
 | 
				
			||||||
 | 
								 info->endpoint, info->addr, info->port);
 | 
				
			||||||
 | 
						else if (info->endpoint[0])
 | 
				
			||||||
 | 
							snprintf(buf, sizeof(buf), "%s", info->endpoint);
 | 
				
			||||||
 | 
						else if (info->addr[0])
 | 
				
			||||||
 | 
							snprintf(buf, sizeof(buf), "%s:%u", info->addr, info->port);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return "empty";
 | 
				
			||||||
 | 
						return buf;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static __attribute__((constructor)) void osmo_mgcp_client_fsm_init()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						OSMO_ASSERT(osmo_fsm_register(&fsm_mgcp_client) == 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										216
									
								
								src/libosmo-mgcp-client/mgcp_client_pool.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										216
									
								
								src/libosmo-mgcp-client/mgcp_client_pool.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,216 @@
 | 
				
			|||||||
 | 
					/* (C) 2021 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Author: Philipp Maier
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/mgcp_client/mgcp_client.h>
 | 
				
			||||||
 | 
					#include <osmocom/mgcp_client/mgcp_client_internal.h>
 | 
				
			||||||
 | 
					#include <osmocom/mgcp_client/mgcp_client_pool_internal.h>
 | 
				
			||||||
 | 
					#include <osmocom/mgcp_client/mgcp_client_pool.h>
 | 
				
			||||||
 | 
					#include <stddef.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LOGPPMGW(pool_member, level, fmt, args...) \
 | 
				
			||||||
 | 
					LOGP(DLMGCP, level, "MGW-pool(%s) " fmt, mgcp_client_pool_member_name(pool_member), ## args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Get a human readable name for a given pool member. */
 | 
				
			||||||
 | 
					const char *mgcp_client_pool_member_name(const struct mgcp_client_pool_member *pool_member)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct mgcp_client *mpcp_client;
 | 
				
			||||||
 | 
						struct mgcp_client mpcp_client_dummy;
 | 
				
			||||||
 | 
						static char name[512];
 | 
				
			||||||
 | 
						const char *description;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!pool_member)
 | 
				
			||||||
 | 
							return "(null)";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* It is not guranteed that a pool_member has an MGCP client. The client may not yet be initialized or the
 | 
				
			||||||
 | 
						 * initalization may have been failed. In this case we will generate a dummy MGCP client to work with. */
 | 
				
			||||||
 | 
						if (!pool_member->client) {
 | 
				
			||||||
 | 
							memcpy(&mpcp_client_dummy.actual, &pool_member->conf, sizeof(mpcp_client_dummy.actual));
 | 
				
			||||||
 | 
							mpcp_client = &mpcp_client_dummy;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							mpcp_client = pool_member->client;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						description = mgcp_client_name(mpcp_client);
 | 
				
			||||||
 | 
						snprintf(name, sizeof(name), "%d:%s", pool_member->nr, description);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return name;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! Allocate MGCP client pool. This is called once on startup and before the pool is used with
 | 
				
			||||||
 | 
					 *  mgcp_client_pool_vty_init(). Since the pool is linked with the VTY it must exist througout the entire runtime.
 | 
				
			||||||
 | 
					 *  \param[in] talloc_ctx talloc context. */
 | 
				
			||||||
 | 
					struct mgcp_client_pool *mgcp_client_pool_alloc(void *talloc_ctx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mgcp_client_pool *pool;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pool = talloc_zero(talloc_ctx, struct mgcp_client_pool);
 | 
				
			||||||
 | 
						if (!pool)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						INIT_LLIST_HEAD(&pool->pool);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return pool;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! Initialize and connect an mcgp client pool.
 | 
				
			||||||
 | 
					 *  \param[in,out] mgcp MGCP client pool descriptor.
 | 
				
			||||||
 | 
					 *  \returns number of successfully initialized pool members. */
 | 
				
			||||||
 | 
					unsigned int mgcp_client_pool_connect(struct mgcp_client_pool *pool)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mgcp_client_pool_member *pool_member;
 | 
				
			||||||
 | 
						unsigned int pool_members_initialized = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						llist_for_each_entry(pool_member, &pool->pool, list) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Initialize client */
 | 
				
			||||||
 | 
							pool_member->client = mgcp_client_init(pool_member, &pool_member->conf);
 | 
				
			||||||
 | 
							if (!pool_member->client) {
 | 
				
			||||||
 | 
								LOGPPMGW(pool_member, LOGL_ERROR, "MGCP client initialization failed\n");
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Set backpointer so that we can detect later that this MGCP client is managed
 | 
				
			||||||
 | 
							 * by this pool. */
 | 
				
			||||||
 | 
							pool_member->client->pool = pool;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Connect client */
 | 
				
			||||||
 | 
							if (mgcp_client_connect2(pool_member->client, 0)) {
 | 
				
			||||||
 | 
								LOGPPMGW(pool_member, LOGL_ERROR, "MGCP client connect failed at (%s:%u)\n",
 | 
				
			||||||
 | 
									 pool_member->conf.remote_addr, pool_member->conf.remote_port);
 | 
				
			||||||
 | 
								talloc_free(pool_member->client);
 | 
				
			||||||
 | 
								pool_member->client = NULL;
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							pool_members_initialized++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return pool_members_initialized;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! register a single mgcp_client instance to the pool.
 | 
				
			||||||
 | 
					 *  \param[out] pool MGCP client pool descriptor.
 | 
				
			||||||
 | 
					 *  \param[in] mgcp MGCP client descriptor. */
 | 
				
			||||||
 | 
					void mgcp_client_pool_register_single(struct mgcp_client_pool *pool, struct mgcp_client *mgcp_client)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/*! Some applications still support the non-pooled MGW VTY configuration variant provided by
 | 
				
			||||||
 | 
						 *  mgcp_client_vty_init(). If this is the case the mgcp_client instance created by mgcp_client_init()
 | 
				
			||||||
 | 
						 *  can be registered here so that it will appear as if it were part of the pool. When the user actively
 | 
				
			||||||
 | 
						 *  configures MGW pool members, the MGCP client registered here will be ignored. (The registration of
 | 
				
			||||||
 | 
						 *  multiple singe mgcp_client instances is not possible.) */
 | 
				
			||||||
 | 
						pool->mgcp_client_single = mgcp_client;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Not every pool member may have a functional MGCP client, we will run through the pool once until we meet a
 | 
				
			||||||
 | 
					 * pool member that is suitable (has a client, is not blocked, has a low load). */
 | 
				
			||||||
 | 
					static struct mgcp_client_pool_member *mgcp_client_pool_pick(struct mgcp_client_pool *pool)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mgcp_client_pool_member *pool_member;
 | 
				
			||||||
 | 
						struct mgcp_client_pool_member *pool_member_picked = NULL;
 | 
				
			||||||
 | 
						unsigned int n_pool_members = llist_count(&pool->pool);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						llist_for_each_entry(pool_member, &pool->pool, list) {
 | 
				
			||||||
 | 
							if (pool_member->blocked == false && pool_member->client) {
 | 
				
			||||||
 | 
								if (!pool_member_picked)
 | 
				
			||||||
 | 
									pool_member_picked = pool_member;
 | 
				
			||||||
 | 
								else if (pool_member_picked->refcount > pool_member->refcount)
 | 
				
			||||||
 | 
									pool_member_picked = pool_member;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								LOGPPMGW(pool_member, LOGL_DEBUG, "MGW pool has %u members -- MGW %u is unusable\n", n_pool_members,
 | 
				
			||||||
 | 
									 pool_member->nr);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (pool_member_picked) {
 | 
				
			||||||
 | 
							LOGPPMGW(pool_member_picked, LOGL_DEBUG, "MGW pool has %u members -- using MGW %u (active calls: %u)\n",
 | 
				
			||||||
 | 
								 n_pool_members, pool_member_picked->nr, pool_member_picked->refcount);
 | 
				
			||||||
 | 
							return pool_member_picked;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						LOGP(DLMGCP, LOGL_ERROR,
 | 
				
			||||||
 | 
						     "MGW pool has %u members, but no functional MGW pool member found -- check configuration!\n",
 | 
				
			||||||
 | 
						     n_pool_members);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! get an MGCP client from the pool (increment reference counter).
 | 
				
			||||||
 | 
					 *  \param[in,out] pool MGCP client pool descriptor.
 | 
				
			||||||
 | 
					 *  \returns MGCP client descriptor, NULL if no member was found (empty pool). */
 | 
				
			||||||
 | 
					struct mgcp_client *mgcp_client_pool_get(struct mgcp_client_pool *pool)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mgcp_client_pool_member *pool_member;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! When an MGCP client is taken from the pool it is still available for other calls. In fact only a reference
 | 
				
			||||||
 | 
						 *  counter is incremented to keep track on how many references to a specific MGCP client are currently used
 | 
				
			||||||
 | 
						 *  by the application code. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* When the pool is empty, return a single MGCP client if it is registered. */
 | 
				
			||||||
 | 
						if (llist_empty(&pool->pool) && pool->mgcp_client_single) {
 | 
				
			||||||
 | 
							LOGP(DLMGCP, LOGL_DEBUG, "MGW pool is empty -- using (single) MGW %s\n",
 | 
				
			||||||
 | 
							     mgcp_client_name(pool->mgcp_client_single));
 | 
				
			||||||
 | 
							return pool->mgcp_client_single;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Abort when the pool is empty */
 | 
				
			||||||
 | 
						if (llist_empty(&pool->pool)) {
 | 
				
			||||||
 | 
							LOGP(DLMGCP, LOGL_ERROR, "MGW pool is empty -- no MGW available!\n");
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Pick a suitable pool member */
 | 
				
			||||||
 | 
						pool_member = mgcp_client_pool_pick(pool);
 | 
				
			||||||
 | 
						if (pool_member) {
 | 
				
			||||||
 | 
							pool_member->refcount++;
 | 
				
			||||||
 | 
							return pool_member->client;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! put an MGCP client back into the pool (decrement reference counter).
 | 
				
			||||||
 | 
					 *  \param[in,out] pool MGCP client pool descriptor.
 | 
				
			||||||
 | 
					 *  \param[in] mgcp MGCP client descriptor.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This function is able to detect automatically to which pool the mgcp_client belongs. If the mgcp_client does
 | 
				
			||||||
 | 
					 * not belong to a pool at all, the function call will have no effect. */
 | 
				
			||||||
 | 
					void mgcp_client_pool_put(struct mgcp_client *mgcp_client)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mgcp_client_pool_member *pool_member;
 | 
				
			||||||
 | 
						struct mgcp_client_pool *pool;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!mgcp_client)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (mgcp_client->pool)
 | 
				
			||||||
 | 
							pool = mgcp_client->pool;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						llist_for_each_entry(pool_member, &pool->pool, list) {
 | 
				
			||||||
 | 
							if (pool_member->client == mgcp_client) {
 | 
				
			||||||
 | 
								if (pool_member->refcount == 0) {
 | 
				
			||||||
 | 
									LOGPPMGW(pool_member, LOGL_ERROR, "MGW pool member has invalid refcount\n");
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								pool_member->refcount--;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -6,16 +6,16 @@
 | 
				
			|||||||
 * All Rights Reserved
 | 
					 * All Rights Reserved
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * This program is free software; you can redistribute it and/or modify
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 * it under the terms of the GNU Affero General Public License as published by
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
					 * the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 * (at your option) any later version.
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * This program is distributed in the hope that it will be useful,
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 * GNU Affero General Public License for more details.
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You should have received a copy of the GNU Affero General Public License
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -24,26 +24,48 @@
 | 
				
			|||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <talloc.h>
 | 
					#include <talloc.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/vty/vty.h>
 | 
				
			||||||
#include <osmocom/vty/command.h>
 | 
					#include <osmocom/vty/command.h>
 | 
				
			||||||
 | 
					#include <osmocom/vty/misc.h>
 | 
				
			||||||
#include <osmocom/core/utils.h>
 | 
					#include <osmocom/core/utils.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <osmocom/mgcp_client/mgcp_client.h>
 | 
					#include <osmocom/mgcp_client/mgcp_client.h>
 | 
				
			||||||
 | 
					#include <osmocom/mgcp_client/mgcp_client_internal.h>
 | 
				
			||||||
 | 
					#include <osmocom/mgcp_client/mgcp_client_pool_internal.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MGW_STR "Configure MGCP connection to Media Gateway\n"
 | 
					#define MGW_STR MGCP_CLIENT_MGW_STR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void *global_mgcp_client_ctx = NULL;
 | 
					/* Only common (non-pooled) VTY connands will use this talloc context. All
 | 
				
			||||||
struct mgcp_client_conf *global_mgcp_client_conf = NULL;
 | 
					 * pooled VTY commands will use the pool (global_mgcp_client_pool) as
 | 
				
			||||||
 | 
					 * talloc context. */
 | 
				
			||||||
 | 
					static void *global_mgcp_client_ctx = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* MGCP Client configuration used with mgcp_client_vty_init(). (This pointer
 | 
				
			||||||
 | 
					 * points to user provided memory, so it cannot be used as talloc context.) */
 | 
				
			||||||
 | 
					static struct mgcp_client_conf *global_mgcp_client_conf = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Pointer to the MGCP pool that is managed by mgcp_client_pool_vty_init() */
 | 
				
			||||||
 | 
					static struct mgcp_client_pool *global_mgcp_client_pool = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct mgcp_client_conf *get_mgcp_client_config(struct vty *vty)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (global_mgcp_client_pool && vty->node == global_mgcp_client_pool->vty_node->node)
 | 
				
			||||||
 | 
							return vty->index;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return global_mgcp_client_conf;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DEFUN(cfg_mgw_local_ip, cfg_mgw_local_ip_cmd,
 | 
					DEFUN(cfg_mgw_local_ip, cfg_mgw_local_ip_cmd,
 | 
				
			||||||
      "mgw local-ip A.B.C.D",
 | 
					      "mgw local-ip " VTY_IPV46_CMD,
 | 
				
			||||||
      MGW_STR "local bind to connect to MGW from\n"
 | 
					      MGW_STR "local bind to connect to MGW from\n"
 | 
				
			||||||
      "local bind IP address\n")
 | 
					      "local bind IPv4 address\n"
 | 
				
			||||||
 | 
					      "local bind IPv6 address\n")
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!global_mgcp_client_conf)
 | 
						struct mgcp_client_conf *conf = get_mgcp_client_config(vty);
 | 
				
			||||||
		return CMD_ERR_NOTHING_TODO;
 | 
					
 | 
				
			||||||
	OSMO_ASSERT(global_mgcp_client_ctx);
 | 
						osmo_talloc_replace_string(global_mgcp_client_ctx,
 | 
				
			||||||
	global_mgcp_client_conf->local_addr =
 | 
									   (char **)&conf->local_addr,
 | 
				
			||||||
		talloc_strdup(global_mgcp_client_ctx, argv[0]);
 | 
									   argv[0]);
 | 
				
			||||||
	return CMD_SUCCESS;
 | 
						return CMD_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
ALIAS_DEPRECATED(cfg_mgw_local_ip, cfg_mgcpgw_local_ip_cmd,
 | 
					ALIAS_DEPRECATED(cfg_mgw_local_ip, cfg_mgcpgw_local_ip_cmd,
 | 
				
			||||||
@@ -56,9 +78,9 @@ DEFUN(cfg_mgw_local_port, cfg_mgw_local_port_cmd,
 | 
				
			|||||||
      MGW_STR "local port to connect to MGW from\n"
 | 
					      MGW_STR "local port to connect to MGW from\n"
 | 
				
			||||||
      "local bind port\n")
 | 
					      "local bind port\n")
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!global_mgcp_client_conf)
 | 
						struct mgcp_client_conf *conf = get_mgcp_client_config(vty);
 | 
				
			||||||
		return CMD_ERR_NOTHING_TODO;
 | 
					
 | 
				
			||||||
	global_mgcp_client_conf->local_port = atoi(argv[0]);
 | 
						conf->local_port = atoi(argv[0]);
 | 
				
			||||||
	return CMD_SUCCESS;
 | 
						return CMD_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
ALIAS_DEPRECATED(cfg_mgw_local_port, cfg_mgcpgw_local_port_cmd,
 | 
					ALIAS_DEPRECATED(cfg_mgw_local_port, cfg_mgcpgw_local_port_cmd,
 | 
				
			||||||
@@ -67,15 +89,15 @@ ALIAS_DEPRECATED(cfg_mgw_local_port, cfg_mgcpgw_local_port_cmd,
 | 
				
			|||||||
		 "local bind port\n")
 | 
							 "local bind port\n")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DEFUN(cfg_mgw_remote_ip, cfg_mgw_remote_ip_cmd,
 | 
					DEFUN(cfg_mgw_remote_ip, cfg_mgw_remote_ip_cmd,
 | 
				
			||||||
      "mgw remote-ip A.B.C.D",
 | 
					      "mgw remote-ip " VTY_IPV46_CMD,
 | 
				
			||||||
      MGW_STR "remote IP address to reach the MGW at\n"
 | 
					      MGW_STR "remote IP address to reach the MGW at\n"
 | 
				
			||||||
      "remote IP address\n")
 | 
					      "remote IPv4 address\n"
 | 
				
			||||||
 | 
					      "remote IPv6 address\n")
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!global_mgcp_client_conf)
 | 
						struct mgcp_client_conf *conf = get_mgcp_client_config(vty);
 | 
				
			||||||
		return CMD_ERR_NOTHING_TODO;
 | 
					
 | 
				
			||||||
	OSMO_ASSERT(global_mgcp_client_ctx);
 | 
						osmo_talloc_replace_string(global_mgcp_client_ctx,
 | 
				
			||||||
	global_mgcp_client_conf->remote_addr =
 | 
									   (char **)&conf->remote_addr, argv[0]);
 | 
				
			||||||
		talloc_strdup(global_mgcp_client_ctx, argv[0]);
 | 
					 | 
				
			||||||
	return CMD_SUCCESS;
 | 
						return CMD_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
ALIAS_DEPRECATED(cfg_mgw_remote_ip, cfg_mgcpgw_remote_ip_cmd,
 | 
					ALIAS_DEPRECATED(cfg_mgw_remote_ip, cfg_mgcpgw_remote_ip_cmd,
 | 
				
			||||||
@@ -88,9 +110,9 @@ DEFUN(cfg_mgw_remote_port, cfg_mgw_remote_port_cmd,
 | 
				
			|||||||
      MGW_STR "remote port to reach the MGW at\n"
 | 
					      MGW_STR "remote port to reach the MGW at\n"
 | 
				
			||||||
      "remote port\n")
 | 
					      "remote port\n")
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!global_mgcp_client_conf)
 | 
						struct mgcp_client_conf *conf = get_mgcp_client_config(vty);
 | 
				
			||||||
		return CMD_ERR_NOTHING_TODO;
 | 
					
 | 
				
			||||||
	global_mgcp_client_conf->remote_port = atoi(argv[0]);
 | 
						conf->remote_port = atoi(argv[0]);
 | 
				
			||||||
	return CMD_SUCCESS;
 | 
						return CMD_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
ALIAS_DEPRECATED(cfg_mgw_remote_port, cfg_mgcpgw_remote_port_cmd,
 | 
					ALIAS_DEPRECATED(cfg_mgw_remote_port, cfg_mgcpgw_remote_port_cmd,
 | 
				
			||||||
@@ -98,25 +120,16 @@ ALIAS_DEPRECATED(cfg_mgw_remote_port, cfg_mgcpgw_remote_port_cmd,
 | 
				
			|||||||
		 MGW_STR "remote bind to connect to MGCP gateway with\n"
 | 
							 MGW_STR "remote bind to connect to MGCP gateway with\n"
 | 
				
			||||||
		 "remote bind port\n")
 | 
							 "remote bind port\n")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DEFUN(cfg_mgw_endpoint_range, cfg_mgw_endpoint_range_cmd,
 | 
					DEFUN_DEPRECATED(cfg_mgw_endpoint_range, cfg_mgw_endpoint_range_cmd,
 | 
				
			||||||
      "mgw endpoint-range <1-65534> <1-65534>",
 | 
					      "mgw endpoint-range <1-65534> <1-65534>",
 | 
				
			||||||
      MGW_STR "usable range of endpoint identifiers\n"
 | 
					      MGW_STR "DEPRECATED: the endpoint range cannot be defined by the client\n"
 | 
				
			||||||
      "set first usable endpoint identifier\n"
 | 
					      "-\n" "-\n")
 | 
				
			||||||
      "set last usable endpoint identifier\n")
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uint16_t first_endpoint = atoi(argv[0]);
 | 
						vty_out(vty, "Please do not use legacy config 'mgw endpoint-range'"
 | 
				
			||||||
	uint16_t last_endpoint = atoi(argv[1]);
 | 
							" (the range can no longer be defined by the MGCP client)%s",
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (last_endpoint < first_endpoint) {
 | 
					 | 
				
			||||||
		vty_out(vty, "last endpoint must be greater than first endpoint!%s",
 | 
					 | 
				
			||||||
		VTY_NEWLINE);
 | 
							VTY_NEWLINE);
 | 
				
			||||||
	return CMD_SUCCESS;
 | 
						return CMD_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	global_mgcp_client_conf->first_endpoint = first_endpoint;
 | 
					 | 
				
			||||||
	global_mgcp_client_conf->last_endpoint = last_endpoint;
 | 
					 | 
				
			||||||
	return CMD_SUCCESS;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
ALIAS_DEPRECATED(cfg_mgw_endpoint_range, cfg_mgcpgw_endpoint_range_cmd,
 | 
					ALIAS_DEPRECATED(cfg_mgw_endpoint_range, cfg_mgcpgw_endpoint_range_cmd,
 | 
				
			||||||
      "mgcpgw endpoint-range <1-65534> <1-65534>",
 | 
					      "mgcpgw endpoint-range <1-65534> <1-65534>",
 | 
				
			||||||
      MGW_STR "usable range of endpoint identifiers\n"
 | 
					      MGW_STR "usable range of endpoint identifiers\n"
 | 
				
			||||||
@@ -125,14 +138,15 @@ ALIAS_DEPRECATED(cfg_mgw_endpoint_range, cfg_mgcpgw_endpoint_range_cmd,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define BTS_START_STR "First UDP port allocated for the BTS side\n"
 | 
					#define BTS_START_STR "First UDP port allocated for the BTS side\n"
 | 
				
			||||||
#define UDP_PORT_STR "UDP Port number\n"
 | 
					#define UDP_PORT_STR "UDP Port number\n"
 | 
				
			||||||
DEFUN(cfg_mgw_rtp_bts_base_port,
 | 
					DEFUN_DEPRECATED(cfg_mgw_rtp_bts_base_port,
 | 
				
			||||||
      cfg_mgw_rtp_bts_base_port_cmd,
 | 
					      cfg_mgw_rtp_bts_base_port_cmd,
 | 
				
			||||||
      "mgw bts-base <0-65534>",
 | 
					      "mgw bts-base <0-65534>",
 | 
				
			||||||
      MGW_STR
 | 
					      MGW_STR
 | 
				
			||||||
      BTS_START_STR
 | 
					      "DEPRECATED: there is no explicit BTS side in current osmo-mgw\n" "-\n")
 | 
				
			||||||
      UDP_PORT_STR)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	global_mgcp_client_conf->bts_base = atoi(argv[0]);
 | 
						vty_out(vty, "Please do not use legacy config 'mgw bts-base'"
 | 
				
			||||||
 | 
							" (there is no explicit BTS side in an MGW anymore)%s",
 | 
				
			||||||
 | 
							VTY_NEWLINE);
 | 
				
			||||||
	return CMD_SUCCESS;
 | 
						return CMD_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
ALIAS_DEPRECATED(cfg_mgw_rtp_bts_base_port,
 | 
					ALIAS_DEPRECATED(cfg_mgw_rtp_bts_base_port,
 | 
				
			||||||
@@ -142,65 +156,402 @@ ALIAS_DEPRECATED(cfg_mgw_rtp_bts_base_port,
 | 
				
			|||||||
      BTS_START_STR
 | 
					      BTS_START_STR
 | 
				
			||||||
      UDP_PORT_STR)
 | 
					      UDP_PORT_STR)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int mgcp_client_config_write(struct vty *vty, const char *indent)
 | 
					DEFUN(cfg_mgw_endpoint_domain_name,
 | 
				
			||||||
 | 
					      cfg_mgw_endpoint_domain_name_cmd,
 | 
				
			||||||
 | 
					      "mgw endpoint-domain NAME",
 | 
				
			||||||
 | 
					      MGW_STR "Set the domain name to send in MGCP messages, e.g. the part 'foo' in 'rtpbridge/*@foo'.\n"
 | 
				
			||||||
 | 
					      "Domain name, should be alphanumeric.\n")
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mgcp_client_conf *conf = get_mgcp_client_config(vty);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (osmo_strlcpy(conf->endpoint_domain_name, argv[0], sizeof(conf->endpoint_domain_name))
 | 
				
			||||||
 | 
						    >= sizeof(conf->endpoint_domain_name)) {
 | 
				
			||||||
 | 
							vty_out(vty, "%% Error: 'mgw endpoint-domain' name too long, max length is %zu: '%s'%s",
 | 
				
			||||||
 | 
								sizeof(conf->endpoint_domain_name) - 1, argv[0], VTY_NEWLINE);
 | 
				
			||||||
 | 
							return CMD_WARNING;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return CMD_SUCCESS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DEFUN(cfg_mgw_reset_ep_name,
 | 
				
			||||||
 | 
					      cfg_mgw_reset_ep_name_cmd,
 | 
				
			||||||
 | 
					      "mgw reset-endpoint NAME",
 | 
				
			||||||
 | 
					      MGW_STR "Add an endpoint name that should be reset (DLCX) on connect to the reset-endpoint list,"
 | 
				
			||||||
 | 
					      "e.g. 'rtpbridge/*'\n"
 | 
				
			||||||
 | 
					      "Endpoint name, e.g. 'rtpbridge/*' or 'ds/e1-0/s-3/su16-4'.\n")
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
						struct reset_ep *reset_ep;
 | 
				
			||||||
 | 
						struct mgcp_client_conf *conf = get_mgcp_client_config(vty);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* stop when the address is already in the list */
 | 
				
			||||||
 | 
						llist_for_each_entry(reset_ep, &conf->reset_epnames, list) {
 | 
				
			||||||
 | 
							if (strcmp(argv[0], reset_ep->name) == 0) {
 | 
				
			||||||
 | 
								vty_out(vty, "%% duplicate endpoint name configured ('%s')%s", argv[0], VTY_NEWLINE);
 | 
				
			||||||
 | 
								return CMD_WARNING;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* the domain name is not part of the actual endpoint name */
 | 
				
			||||||
 | 
						if (strchr(argv[0], '@')) {
 | 
				
			||||||
 | 
							vty_out(vty, "%% the endpoint name must be given without domain name ('%s')%s",
 | 
				
			||||||
 | 
								argv[0], VTY_NEWLINE);
 | 
				
			||||||
 | 
							return CMD_WARNING;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						reset_ep = talloc_zero(global_mgcp_client_ctx, struct reset_ep);
 | 
				
			||||||
 | 
						OSMO_ASSERT(reset_ep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc = osmo_strlcpy(reset_ep->name, argv[0], sizeof(reset_ep->name));
 | 
				
			||||||
 | 
						if (rc >= sizeof(reset_ep->name)) {
 | 
				
			||||||
 | 
							vty_out(vty, "%% Error: 'mgw reset-endpoint' name too long, max length is %zu: '%s'%s",
 | 
				
			||||||
 | 
								sizeof(reset_ep->name) - 1, argv[0], VTY_NEWLINE);
 | 
				
			||||||
 | 
							talloc_free(reset_ep);
 | 
				
			||||||
 | 
							return CMD_WARNING;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						llist_add_tail(&reset_ep->list, &conf->reset_epnames);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return CMD_SUCCESS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DEFUN(cfg_mgw_no_reset_ep_name,
 | 
				
			||||||
 | 
					      cfg_mgw_no_reset_ep_name_cmd,
 | 
				
			||||||
 | 
					      "no mgw reset-endpoint NAME",
 | 
				
			||||||
 | 
					      NO_STR MGW_STR "remove an endpoint name from the reset-endpoint list, e.g. 'rtpbridge/*'\n"
 | 
				
			||||||
 | 
					      "Endpoint name, e.g. 'rtpbridge/*' or 'ds/e1-0/s-3/su16-4'.\n")
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct reset_ep *reset_ep;
 | 
				
			||||||
 | 
						struct mgcp_client_conf *conf = get_mgcp_client_config(vty);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						llist_for_each_entry(reset_ep, &conf->reset_epnames, list) {
 | 
				
			||||||
 | 
							if (strcmp(argv[0], reset_ep->name) == 0) {
 | 
				
			||||||
 | 
								llist_del(&reset_ep->list);
 | 
				
			||||||
 | 
								talloc_free(reset_ep);
 | 
				
			||||||
 | 
								return CMD_SUCCESS;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vty_out(vty, "%% no such endpoint name configured ('%s')%s", argv[0], VTY_NEWLINE);
 | 
				
			||||||
 | 
						return CMD_WARNING;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int config_write(struct vty *vty, const char *indent, struct mgcp_client_conf *conf)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const char *addr;
 | 
						const char *addr;
 | 
				
			||||||
	int port;
 | 
						int port;
 | 
				
			||||||
	uint16_t first_endpoint;
 | 
						struct reset_ep *reset_ep;
 | 
				
			||||||
	uint16_t last_endpoint;
 | 
					 | 
				
			||||||
	uint16_t bts_base;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	addr = global_mgcp_client_conf->local_addr;
 | 
						if (conf->description)
 | 
				
			||||||
 | 
							vty_out(vty, "%sdescription %s%s", indent, conf->description, VTY_NEWLINE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						addr = conf->local_addr;
 | 
				
			||||||
	if (addr)
 | 
						if (addr)
 | 
				
			||||||
		vty_out(vty, "%smgw local-ip %s%s", indent, addr,
 | 
							vty_out(vty, "%smgw local-ip %s%s", indent, addr,
 | 
				
			||||||
			VTY_NEWLINE);
 | 
								VTY_NEWLINE);
 | 
				
			||||||
	port = global_mgcp_client_conf->local_port;
 | 
						port = conf->local_port;
 | 
				
			||||||
	if (port >= 0)
 | 
						if (port >= 0)
 | 
				
			||||||
		vty_out(vty, "%smgw local-port %u%s", indent,
 | 
							vty_out(vty, "%smgw local-port %u%s", indent,
 | 
				
			||||||
			(uint16_t)port, VTY_NEWLINE);
 | 
								(uint16_t)port, VTY_NEWLINE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	addr = global_mgcp_client_conf->remote_addr;
 | 
						addr = conf->remote_addr;
 | 
				
			||||||
	if (addr)
 | 
						if (addr)
 | 
				
			||||||
		vty_out(vty, "%smgw remote-ip %s%s", indent, addr,
 | 
							vty_out(vty, "%smgw remote-ip %s%s", indent, addr,
 | 
				
			||||||
			VTY_NEWLINE);
 | 
								VTY_NEWLINE);
 | 
				
			||||||
	port = global_mgcp_client_conf->remote_port;
 | 
						port = conf->remote_port;
 | 
				
			||||||
	if (port >= 0)
 | 
						if (port >= 0)
 | 
				
			||||||
		vty_out(vty, "%smgw remote-port %u%s", indent,
 | 
							vty_out(vty, "%smgw remote-port %u%s", indent,
 | 
				
			||||||
			(uint16_t)port, VTY_NEWLINE);
 | 
								(uint16_t)port, VTY_NEWLINE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	first_endpoint = global_mgcp_client_conf->first_endpoint;
 | 
						if (conf->endpoint_domain_name[0])
 | 
				
			||||||
	last_endpoint = global_mgcp_client_conf->last_endpoint;
 | 
							vty_out(vty, "%smgw endpoint-domain %s%s", indent,
 | 
				
			||||||
	if (last_endpoint != 0) {
 | 
								conf->endpoint_domain_name, VTY_NEWLINE);
 | 
				
			||||||
		vty_out(vty, "%smgw endpoint-range %u %u%s", indent,
 | 
					
 | 
				
			||||||
			first_endpoint, last_endpoint, VTY_NEWLINE);
 | 
						llist_for_each_entry(reset_ep, &conf->reset_epnames, list)
 | 
				
			||||||
 | 
							vty_out(vty, "%smgw reset-endpoint %s%s", indent, reset_ep->name, VTY_NEWLINE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return CMD_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bts_base = global_mgcp_client_conf->bts_base;
 | 
					/*! Write out MGCP client config to VTY.
 | 
				
			||||||
	if (bts_base) {
 | 
					 *  \param[in] vty VTY to which we should print.
 | 
				
			||||||
		vty_out(vty, "%smgw bts-base %u%s", indent,
 | 
					 *  \param[in] string used for indentation (e.g. " ").
 | 
				
			||||||
			bts_base, VTY_NEWLINE);
 | 
					 *  \returns CMD_SUCCESS on success, CMD_WARNING on error */
 | 
				
			||||||
 | 
					int mgcp_client_config_write(struct vty *vty, const char *indent)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return config_write(vty, indent, global_mgcp_client_conf);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void vty_init_common(void *talloc_ctx, int node)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						global_mgcp_client_ctx = talloc_ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						install_lib_element(node, &cfg_mgw_local_ip_cmd);
 | 
				
			||||||
 | 
						install_lib_element(node, &cfg_mgw_local_port_cmd);
 | 
				
			||||||
 | 
						install_lib_element(node, &cfg_mgw_remote_ip_cmd);
 | 
				
			||||||
 | 
						install_lib_element(node, &cfg_mgw_remote_port_cmd);
 | 
				
			||||||
 | 
						install_lib_element(node, &cfg_mgw_endpoint_range_cmd);
 | 
				
			||||||
 | 
						install_lib_element(node, &cfg_mgw_rtp_bts_base_port_cmd);
 | 
				
			||||||
 | 
						install_lib_element(node, &cfg_mgw_endpoint_domain_name_cmd);
 | 
				
			||||||
 | 
						install_lib_element(node, &cfg_mgw_reset_ep_name_cmd);
 | 
				
			||||||
 | 
						install_lib_element(node, &cfg_mgw_no_reset_ep_name_cmd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						osmo_fsm_vty_add_cmds();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! Set up MGCP client VTY
 | 
				
			||||||
 | 
					 *  (called once at startup by the application process).
 | 
				
			||||||
 | 
					 *  \param[in] talloc_ctx talloc context to be used by the VTY for allocating memory.
 | 
				
			||||||
 | 
					 *  \param[in] node identifier of the node on which the VTY commands should be installed.
 | 
				
			||||||
 | 
					 *  \param[in] conf user provided memory to to store the MGCP client configuration data. */
 | 
				
			||||||
 | 
					void mgcp_client_vty_init(void *talloc_ctx, int node, struct mgcp_client_conf *conf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						global_mgcp_client_conf = conf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* deprecated 'mgcpgw' commands */
 | 
				
			||||||
 | 
						install_lib_element(node, &cfg_mgcpgw_local_ip_cmd);
 | 
				
			||||||
 | 
						install_lib_element(node, &cfg_mgcpgw_local_port_cmd);
 | 
				
			||||||
 | 
						install_lib_element(node, &cfg_mgcpgw_remote_ip_cmd);
 | 
				
			||||||
 | 
						install_lib_element(node, &cfg_mgcpgw_remote_port_cmd);
 | 
				
			||||||
 | 
						install_lib_element(node, &cfg_mgcpgw_endpoint_range_cmd);
 | 
				
			||||||
 | 
						install_lib_element(node, &cfg_mgcpgw_rtp_bts_base_port_cmd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vty_init_common(talloc_ctx, node);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int config_write_pool(struct vty *vty)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mgcp_client_pool *pool = global_mgcp_client_pool;
 | 
				
			||||||
 | 
						struct mgcp_client_pool_member *pool_member;
 | 
				
			||||||
 | 
						unsigned int indent_buf_len = strlen(pool->vty_indent) + 1 + 1;
 | 
				
			||||||
 | 
						char *indent = talloc_zero_size(vty, indent_buf_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						snprintf(indent, indent_buf_len, "%s ", pool->vty_indent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						llist_for_each_entry(pool_member, &pool->pool, list) {
 | 
				
			||||||
 | 
							vty_out(vty, "%smgw %u%s", pool->vty_indent, pool_member->nr, VTY_NEWLINE);
 | 
				
			||||||
 | 
							config_write(vty, indent, &pool_member->conf);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						talloc_free(indent);
 | 
				
			||||||
 | 
						return CMD_SUCCESS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Lookup the selected MGCP client config by its reference number */
 | 
				
			||||||
 | 
					static struct mgcp_client_pool_member *pool_member_by_nr(unsigned int nr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mgcp_client_pool_member *pool_member = NULL;
 | 
				
			||||||
 | 
						struct mgcp_client_pool_member *pool_member_tmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						llist_for_each_entry(pool_member_tmp, &global_mgcp_client_pool->pool, list) {
 | 
				
			||||||
 | 
							if (pool_member_tmp->nr == nr) {
 | 
				
			||||||
 | 
								pool_member = pool_member_tmp;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return pool_member;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DEFUN_ATTR(cfg_mgw,
 | 
				
			||||||
 | 
						   cfg_mgw_cmd, "mgw <0-255>", "Select a MGCP client config to setup\n" "reference number\n", CMD_ATTR_IMMEDIATE)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int nr = atoi(argv[0]);
 | 
				
			||||||
 | 
						struct mgcp_client_pool_member *pool_member;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pool_member = pool_member_by_nr(nr);
 | 
				
			||||||
 | 
						if (!pool_member) {
 | 
				
			||||||
 | 
							pool_member = talloc_zero(global_mgcp_client_pool, struct mgcp_client_pool_member);
 | 
				
			||||||
 | 
							OSMO_ASSERT(pool_member);
 | 
				
			||||||
 | 
							mgcp_client_conf_init(&pool_member->conf);
 | 
				
			||||||
 | 
							pool_member->nr = nr;
 | 
				
			||||||
 | 
							llist_add_tail(&pool_member->list, &global_mgcp_client_pool->pool);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vty->index = &pool_member->conf;
 | 
				
			||||||
 | 
						vty->index_sub = &pool_member->conf.description;
 | 
				
			||||||
 | 
						vty->node = global_mgcp_client_pool->vty_node->node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return CMD_SUCCESS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DEFUN_ATTR(cfg_no_mgw,
 | 
				
			||||||
 | 
						   cfg_no_mgw_cmd,
 | 
				
			||||||
 | 
						   "no mgw <0-255>", NO_STR "Select a MGCP client config to remove\n" "reference number\n", CMD_ATTR_IMMEDIATE)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int nr = atoi(argv[0]);
 | 
				
			||||||
 | 
						struct mgcp_client_pool_member *pool_member;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pool_member = pool_member_by_nr(nr);
 | 
				
			||||||
 | 
						if (!pool_member) {
 | 
				
			||||||
 | 
							vty_out(vty, "%% no such MGCP client configured ('%s')%s", argv[0], VTY_NEWLINE);
 | 
				
			||||||
 | 
							return CMD_WARNING;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Make sure that there are no ongoing calls */
 | 
				
			||||||
 | 
						if (pool_member->refcount > 0) {
 | 
				
			||||||
 | 
							vty_out(vty, "%% MGCP client (MGW %s) is still serving ongoing calls -- can't remove it now!%s",
 | 
				
			||||||
 | 
								mgcp_client_pool_member_name(pool_member), VTY_NEWLINE);
 | 
				
			||||||
 | 
							return CMD_WARNING;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						llist_del(&pool_member->list);
 | 
				
			||||||
 | 
						if (pool_member->client) {
 | 
				
			||||||
 | 
							mgcp_client_disconnect(pool_member->client);
 | 
				
			||||||
 | 
							talloc_free(pool_member->client);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						talloc_free(pool_member);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return CMD_SUCCESS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DEFUN_ATTR(mgw_reconnect, mgw_reconnect_cmd,
 | 
				
			||||||
 | 
						   "mgw <0-255> reconnect",
 | 
				
			||||||
 | 
						   MGW_STR "reference number\n" "reconfigure and reconnect MGCP client\n", CMD_ATTR_IMMEDIATE)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int nr = atoi(argv[0]);
 | 
				
			||||||
 | 
						struct mgcp_client_pool_member *pool_member = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pool_member = pool_member_by_nr(nr);
 | 
				
			||||||
 | 
						if (!pool_member) {
 | 
				
			||||||
 | 
							vty_out(vty, "%% no such MGCP client configured ('%s')%s", argv[0], VTY_NEWLINE);
 | 
				
			||||||
 | 
							return CMD_WARNING;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Make sure that there are no ongoing calls */
 | 
				
			||||||
 | 
						if (pool_member->refcount > 0) {
 | 
				
			||||||
 | 
							vty_out(vty, "%% MGCP client (MGW %s) is still serving ongoing calls -- can't reconnect it now!%s",
 | 
				
			||||||
 | 
								mgcp_client_pool_member_name(pool_member), VTY_NEWLINE);
 | 
				
			||||||
 | 
							return CMD_WARNING;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Get rid of a possibly existing old MGCP client instance first */
 | 
				
			||||||
 | 
						if (pool_member->client) {
 | 
				
			||||||
 | 
							mgcp_client_disconnect(pool_member->client);
 | 
				
			||||||
 | 
							talloc_free(pool_member->client);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Create a new MGCP client instance with the current config */
 | 
				
			||||||
 | 
						pool_member->client = mgcp_client_init(pool_member, &pool_member->conf);
 | 
				
			||||||
 | 
						if (!pool_member->client) {
 | 
				
			||||||
 | 
							LOGP(DLMGCP, LOGL_ERROR, "(manual) MGW %s initalization failed\n",
 | 
				
			||||||
 | 
							     mgcp_client_pool_member_name(pool_member));
 | 
				
			||||||
 | 
							vty_out(vty, "%% MGCP client (MGW %s) initalization failed ('%s')%s",
 | 
				
			||||||
 | 
								mgcp_client_pool_member_name(pool_member), argv[0], VTY_NEWLINE);
 | 
				
			||||||
 | 
							return CMD_WARNING;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Set backpointer so that we can detect later that this MGCP client is managed by this pool. */
 | 
				
			||||||
 | 
						pool_member->client->pool = global_mgcp_client_pool;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Connect client */
 | 
				
			||||||
 | 
						if (mgcp_client_connect(pool_member->client)) {
 | 
				
			||||||
 | 
							LOGP(DLMGCP, LOGL_ERROR, "(manual) MGW %s connect failed at (%s:%u)\n",
 | 
				
			||||||
 | 
							     mgcp_client_pool_member_name(pool_member), pool_member->conf.remote_addr,
 | 
				
			||||||
 | 
							     pool_member->conf.remote_port);
 | 
				
			||||||
 | 
							talloc_free(pool_member->client);
 | 
				
			||||||
 | 
							pool_member->client = NULL;
 | 
				
			||||||
 | 
							vty_out(vty, "%% MGCP client (MGW %s) initalization failed ('%s')%s",
 | 
				
			||||||
 | 
								mgcp_client_pool_member_name(pool_member), argv[0], VTY_NEWLINE);
 | 
				
			||||||
 | 
							return CMD_WARNING;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return CMD_SUCCESS;
 | 
						return CMD_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void mgcp_client_vty_init(void *talloc_ctx, int node, struct mgcp_client_conf *conf)
 | 
					DEFUN_ATTR(mgw_block, mgw_block_cmd,
 | 
				
			||||||
 | 
						   "mgw <0-255> block",
 | 
				
			||||||
 | 
						   MGW_STR "reference number\n" "block MGCP client so that it won't be used for new calls\n", CMD_ATTR_IMMEDIATE)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	global_mgcp_client_ctx = talloc_ctx;
 | 
						int nr = atoi(argv[0]);
 | 
				
			||||||
	global_mgcp_client_conf = conf;
 | 
						struct mgcp_client_pool_member *pool_member = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	install_element(node, &cfg_mgw_local_ip_cmd);
 | 
						pool_member = pool_member_by_nr(nr);
 | 
				
			||||||
	install_element(node, &cfg_mgw_local_port_cmd);
 | 
						if (!pool_member) {
 | 
				
			||||||
	install_element(node, &cfg_mgw_remote_ip_cmd);
 | 
							vty_out(vty, "%% no such MGCP client configured ('%s')%s", argv[0], VTY_NEWLINE);
 | 
				
			||||||
	install_element(node, &cfg_mgw_remote_port_cmd);
 | 
							return CMD_WARNING;
 | 
				
			||||||
	install_element(node, &cfg_mgw_endpoint_range_cmd);
 | 
						}
 | 
				
			||||||
	install_element(node, &cfg_mgw_rtp_bts_base_port_cmd);
 | 
					
 | 
				
			||||||
 | 
						pool_member->blocked = true;
 | 
				
			||||||
	/* deprecated 'mgcpgw' commands */
 | 
						return CMD_SUCCESS;
 | 
				
			||||||
	install_element(node, &cfg_mgcpgw_local_ip_cmd);
 | 
					}
 | 
				
			||||||
	install_element(node, &cfg_mgcpgw_local_port_cmd);
 | 
					
 | 
				
			||||||
	install_element(node, &cfg_mgcpgw_remote_ip_cmd);
 | 
					DEFUN_ATTR(mgw_unblock, mgw_unblock_cmd,
 | 
				
			||||||
	install_element(node, &cfg_mgcpgw_remote_port_cmd);
 | 
						   "mgw <0-255> unblock",
 | 
				
			||||||
	install_element(node, &cfg_mgcpgw_endpoint_range_cmd);
 | 
						   MGW_STR "reference number\n" "unblock MGCP client so that it will be available for new calls\n", CMD_ATTR_IMMEDIATE)
 | 
				
			||||||
	install_element(node, &cfg_mgcpgw_rtp_bts_base_port_cmd);
 | 
					{
 | 
				
			||||||
 | 
						int nr = atoi(argv[0]);
 | 
				
			||||||
 | 
						struct mgcp_client_pool_member *pool_member = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pool_member = pool_member_by_nr(nr);
 | 
				
			||||||
 | 
						if (!pool_member) {
 | 
				
			||||||
 | 
							vty_out(vty, "%% no such MGCP client configured ('%s')%s", argv[0], VTY_NEWLINE);
 | 
				
			||||||
 | 
							return CMD_WARNING;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pool_member->blocked = false;
 | 
				
			||||||
 | 
						return CMD_SUCCESS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DEFUN(mgw_show, mgw_snow_cmd, "show mgw-pool", SHOW_STR "Display information about the MGW-Pool\n")
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						vty_out(vty, "%% MGW-Pool:%s", VTY_NEWLINE);
 | 
				
			||||||
 | 
						struct mgcp_client_pool_member *pool_member;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (llist_empty(&global_mgcp_client_pool->pool) && global_mgcp_client_pool->mgcp_client_single) {
 | 
				
			||||||
 | 
							vty_out(vty, "%%  (pool is empty, single MGCP client will be used)%s", VTY_NEWLINE);
 | 
				
			||||||
 | 
							return CMD_SUCCESS;
 | 
				
			||||||
 | 
						} else if (llist_empty(&global_mgcp_client_pool->pool)) {
 | 
				
			||||||
 | 
							vty_out(vty, "%%  (pool is empty)%s", VTY_NEWLINE);
 | 
				
			||||||
 | 
							return CMD_SUCCESS;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						llist_for_each_entry(pool_member, &global_mgcp_client_pool->pool, list) {
 | 
				
			||||||
 | 
							vty_out(vty, "%%  MGW %s%s", mgcp_client_pool_member_name(pool_member), VTY_NEWLINE);
 | 
				
			||||||
 | 
							vty_out(vty, "%%   mgcp-client:   %s%s", pool_member->client ? "connected" : "disconnected",
 | 
				
			||||||
 | 
								VTY_NEWLINE);
 | 
				
			||||||
 | 
							vty_out(vty, "%%   service:       %s%s", pool_member->blocked ? "blocked" : "unblocked", VTY_NEWLINE);
 | 
				
			||||||
 | 
							vty_out(vty, "%%   ongoing calls: %u%s", pool_member->refcount, VTY_NEWLINE);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return CMD_SUCCESS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! Set up MGCP client VTY (pooled)
 | 
				
			||||||
 | 
					 *  (called once at startup by the application process).
 | 
				
			||||||
 | 
					 *  \param[in] parent_node identifier of the parent node on which the mgw node appears.
 | 
				
			||||||
 | 
					 *  \param[in] mgw_node identifier that should be used with the newly installed MGW node.
 | 
				
			||||||
 | 
					 *  \param[in] indent indentation string to match the indentation in the VTY config
 | 
				
			||||||
 | 
					 *  \param[in] pool user provided memory to store the configured MGCP client (MGW) pool. */
 | 
				
			||||||
 | 
					void mgcp_client_pool_vty_init(int parent_node, int mgw_node, const char *indent, struct mgcp_client_pool *pool)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/* A pool must be allocated before this function can be called */
 | 
				
			||||||
 | 
						OSMO_ASSERT(pool);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Never allow this function to be called twice on the same pool */
 | 
				
			||||||
 | 
						OSMO_ASSERT(!pool->vty_indent);
 | 
				
			||||||
 | 
						OSMO_ASSERT(!pool->vty_node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pool->vty_indent = talloc_strdup(pool, indent);
 | 
				
			||||||
 | 
						OSMO_ASSERT(pool->vty_indent);
 | 
				
			||||||
 | 
						pool->vty_node = talloc_zero(pool, struct cmd_node);
 | 
				
			||||||
 | 
						OSMO_ASSERT(pool->vty_node);
 | 
				
			||||||
 | 
						pool->vty_node->node = mgw_node;
 | 
				
			||||||
 | 
						pool->vty_node->vtysh = 1;
 | 
				
			||||||
 | 
						pool->vty_node->prompt = talloc_strdup(pool->vty_node, "%s(config-mgw)# ");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						install_lib_element(parent_node, &cfg_mgw_cmd);
 | 
				
			||||||
 | 
						install_lib_element(parent_node, &cfg_no_mgw_cmd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						install_node(pool->vty_node, config_write_pool);
 | 
				
			||||||
 | 
						vty_init_common(pool, mgw_node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						install_element(mgw_node, &cfg_description_cmd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						install_lib_element(ENABLE_NODE, &mgw_reconnect_cmd);
 | 
				
			||||||
 | 
						install_lib_element(ENABLE_NODE, &mgw_block_cmd);
 | 
				
			||||||
 | 
						install_lib_element(ENABLE_NODE, &mgw_unblock_cmd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						install_lib_element_ve(&mgw_snow_cmd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						global_mgcp_client_pool = pool;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,40 +7,45 @@ AM_CPPFLAGS = \
 | 
				
			|||||||
AM_CFLAGS = \
 | 
					AM_CFLAGS = \
 | 
				
			||||||
	-Wall \
 | 
						-Wall \
 | 
				
			||||||
	$(LIBOSMOCORE_CFLAGS) \
 | 
						$(LIBOSMOCORE_CFLAGS) \
 | 
				
			||||||
 | 
						$(LIBOSMOGSM_CFLAGS) \
 | 
				
			||||||
	$(LIBOSMOVTY_CFLAGS) \
 | 
						$(LIBOSMOVTY_CFLAGS) \
 | 
				
			||||||
	$(LIBOSMONETIF_CFLAGS) \
 | 
						$(LIBOSMONETIF_CFLAGS) \
 | 
				
			||||||
 | 
						$(LIBOSMOABIS_CFLAGS) \
 | 
				
			||||||
 | 
						$(LIBOSMOTRAU_CFLAGS) \
 | 
				
			||||||
	$(COVERAGE_CFLAGS) \
 | 
						$(COVERAGE_CFLAGS) \
 | 
				
			||||||
	$(NULL)
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AM_LDFLAGS = \
 | 
					AM_LDFLAGS = \
 | 
				
			||||||
	$(LIBOSMOCORE_LIBS) \
 | 
						$(LIBOSMOCORE_LIBS) \
 | 
				
			||||||
 | 
						$(LIBOSMOGSM_LIBS) \
 | 
				
			||||||
	$(LIBOSMOVTY_LIBS) \
 | 
						$(LIBOSMOVTY_LIBS) \
 | 
				
			||||||
	$(LIBOSMONETIF_LIBS) \
 | 
						$(LIBOSMONETIF_LIBS) \
 | 
				
			||||||
 | 
						$(LIBOSMOABIS_LIBS) \
 | 
				
			||||||
 | 
						$(LIBOSMOTRAU_LIBS) \
 | 
				
			||||||
	$(COVERAGE_LDFLAGS) \
 | 
						$(COVERAGE_LDFLAGS) \
 | 
				
			||||||
	$(NULL)
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# This is not at all related to the release version, but a range of supported
 | 
					noinst_LIBRARIES = \
 | 
				
			||||||
# API versions. Read TODO_RELEASE in the source tree's root!
 | 
						libosmo-mgcp.a \
 | 
				
			||||||
MGCP_LIBVERSION=1:0:0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
lib_LTLIBRARIES = \
 | 
					 | 
				
			||||||
	libosmo-mgcp.la \
 | 
					 | 
				
			||||||
	$(NULL)
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
noinst_HEADERS = \
 | 
					noinst_HEADERS = \
 | 
				
			||||||
	g711common.h \
 | 
						g711common.h \
 | 
				
			||||||
	$(NULL)
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
libosmo_mgcp_la_SOURCES = \
 | 
					libosmo_mgcp_a_SOURCES = \
 | 
				
			||||||
	mgcp_protocol.c \
 | 
						mgcp_protocol.c \
 | 
				
			||||||
	mgcp_network.c \
 | 
						mgcp_network.c \
 | 
				
			||||||
	mgcp_vty.c \
 | 
						mgcp_vty.c \
 | 
				
			||||||
	mgcp_osmux.c \
 | 
						mgcp_osmux.c \
 | 
				
			||||||
	mgcp_sdp.c \
 | 
						mgcp_sdp.c \
 | 
				
			||||||
 | 
						mgcp_codec.c \
 | 
				
			||||||
	mgcp_msg.c \
 | 
						mgcp_msg.c \
 | 
				
			||||||
	mgcp_conn.c \
 | 
						mgcp_conn.c \
 | 
				
			||||||
	mgcp_stat.c \
 | 
						mgcp_stat.c \
 | 
				
			||||||
	mgcp_ep.c \
 | 
						mgcp_endp.c \
 | 
				
			||||||
 | 
						mgcp_trunk.c \
 | 
				
			||||||
 | 
						mgcp_ctrl.c \
 | 
				
			||||||
 | 
						mgcp_ratectr.c \
 | 
				
			||||||
 | 
						mgcp_e1.c \
 | 
				
			||||||
	$(NULL)
 | 
						$(NULL)
 | 
				
			||||||
 | 
					 | 
				
			||||||
libosmo_mgcp_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(MGCP_LIBVERSION)
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										459
									
								
								src/libosmo-mgcp/mgcp_codec.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										459
									
								
								src/libosmo-mgcp/mgcp_codec.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,459 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * (C) 2009-2015 by Holger Hans Peter Freyther <zecke@selfish.org>
 | 
				
			||||||
 | 
					 * (C) 2009-2014 by On-Waves
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU Affero General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU Affero General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU Affero General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#include <osmocom/mgcp/mgcp.h>
 | 
				
			||||||
 | 
					#include <osmocom/mgcp/osmux.h>
 | 
				
			||||||
 | 
					#include <osmocom/mgcp/mgcp_conn.h>
 | 
				
			||||||
 | 
					#include <osmocom/mgcp/mgcp_protocol.h>
 | 
				
			||||||
 | 
					#include <osmocom/mgcp/mgcp_endp.h>
 | 
				
			||||||
 | 
					#include <osmocom/mgcp/mgcp_trunk.h>
 | 
				
			||||||
 | 
					#include <osmocom/mgcp/mgcp_codec.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Helper function to dump codec information of a specified codec to a printable
 | 
				
			||||||
 | 
					 * string, used by dump_codec_summary() */
 | 
				
			||||||
 | 
					static char *dump_codec(struct mgcp_rtp_codec *codec)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						static char str[256];
 | 
				
			||||||
 | 
						char *pt_str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (codec->payload_type > 76)
 | 
				
			||||||
 | 
							pt_str = "DYNAMIC";
 | 
				
			||||||
 | 
						else if (codec->payload_type > 72)
 | 
				
			||||||
 | 
							pt_str = "RESERVED <!>";
 | 
				
			||||||
 | 
						else if (codec->payload_type != PTYPE_UNDEFINED)
 | 
				
			||||||
 | 
							pt_str = codec->subtype_name;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							pt_str = "INVALID <!>";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						snprintf(str, sizeof(str), "(pt:%i=%s, audio:%s subt=%s, rate=%u, ch=%i, t=%u/%u)", codec->payload_type, pt_str,
 | 
				
			||||||
 | 
							 codec->audio_name, codec->subtype_name, codec->rate, codec->channels, codec->frame_duration_num,
 | 
				
			||||||
 | 
							 codec->frame_duration_den);
 | 
				
			||||||
 | 
						return str;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! Dump a summary of all negotiated codecs to debug log
 | 
				
			||||||
 | 
					 *  \param[in] conn related rtp-connection. */
 | 
				
			||||||
 | 
					void mgcp_codec_summary(struct mgcp_conn_rtp *conn)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mgcp_rtp_end *rtp;
 | 
				
			||||||
 | 
						unsigned int i;
 | 
				
			||||||
 | 
						struct mgcp_rtp_codec *codec;
 | 
				
			||||||
 | 
						struct mgcp_endpoint *endp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rtp = &conn->end;
 | 
				
			||||||
 | 
						endp = conn->conn->endp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (rtp->codecs_assigned == 0) {
 | 
				
			||||||
 | 
							LOGPENDP(endp, DLMGCP, LOGL_ERROR, "conn:%s no codecs available\n",
 | 
				
			||||||
 | 
								 mgcp_conn_dump(conn->conn));
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Store parsed codec information */
 | 
				
			||||||
 | 
						for (i = 0; i < rtp->codecs_assigned; i++) {
 | 
				
			||||||
 | 
							codec = &rtp->codecs[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							LOGPENDP(endp, DLMGCP, LOGL_DEBUG, "conn:%s codecs[%u]:%s",
 | 
				
			||||||
 | 
								 mgcp_conn_dump(conn->conn), i, dump_codec(codec));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (codec == rtp->codec)
 | 
				
			||||||
 | 
								LOGPC(DLMGCP, LOGL_DEBUG, " [selected]");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							LOGPC(DLMGCP, LOGL_DEBUG, "\n");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Initalize or reset codec information with default data. */
 | 
				
			||||||
 | 
					static void codec_init(struct mgcp_rtp_codec *codec)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						*codec = (struct mgcp_rtp_codec){
 | 
				
			||||||
 | 
							.payload_type = -1,
 | 
				
			||||||
 | 
							.frame_duration_num = DEFAULT_RTP_AUDIO_FRAME_DUR_NUM,
 | 
				
			||||||
 | 
							.frame_duration_den = DEFAULT_RTP_AUDIO_FRAME_DUR_DEN,
 | 
				
			||||||
 | 
							.rate = DEFAULT_RTP_AUDIO_DEFAULT_RATE,
 | 
				
			||||||
 | 
							.channels = DEFAULT_RTP_AUDIO_DEFAULT_CHANNELS,
 | 
				
			||||||
 | 
							.subtype_name = "",
 | 
				
			||||||
 | 
							.audio_name = "",
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void codec_free(struct mgcp_rtp_codec *codec)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						*codec = (struct mgcp_rtp_codec){};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! Initalize or reset codec information with default data.
 | 
				
			||||||
 | 
					 *  \param[out] conn related rtp-connection. */
 | 
				
			||||||
 | 
					void mgcp_codec_reset_all(struct mgcp_conn_rtp *conn)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						for (i = 0; i < conn->end.codecs_assigned; i++)
 | 
				
			||||||
 | 
							codec_free(&conn->end.codecs[i]);
 | 
				
			||||||
 | 
						conn->end.codecs_assigned = 0;
 | 
				
			||||||
 | 
						conn->end.codec = NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! Add codec configuration depending on payload type and/or codec name. This
 | 
				
			||||||
 | 
					 *  function uses the input parameters to extrapolate the full codec information.
 | 
				
			||||||
 | 
					 *  \param[out] codec configuration (caller provided memory).
 | 
				
			||||||
 | 
					 *  \param[out] conn related rtp-connection.
 | 
				
			||||||
 | 
					 *  \param[in] payload_type codec type id (e.g. 3 for GSM, -1 when undefined).
 | 
				
			||||||
 | 
					 *  \param[in] audio_name audio codec name, in uppercase (e.g. "GSM/8000/1").
 | 
				
			||||||
 | 
					 *  \param[in] param optional codec parameters (set to NULL when unused).
 | 
				
			||||||
 | 
					 *  \returns 0 on success, -EINVAL on failure. */
 | 
				
			||||||
 | 
					int mgcp_codec_add(struct mgcp_conn_rtp *conn, int payload_type, const char *audio_name, const struct mgcp_codec_param *param)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rate;
 | 
				
			||||||
 | 
						int channels;
 | 
				
			||||||
 | 
						struct mgcp_rtp_codec *codec;
 | 
				
			||||||
 | 
						unsigned int pt_offset = conn->end.codecs_assigned;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* The amount of codecs we can store is limited, make sure we do not
 | 
				
			||||||
 | 
						 * overrun this limit. */
 | 
				
			||||||
 | 
						if (conn->end.codecs_assigned >= MGCP_MAX_CODECS)
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* First unused entry */
 | 
				
			||||||
 | 
						codec = &conn->end.codecs[conn->end.codecs_assigned];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Initalize the codec struct with some default data to begin with */
 | 
				
			||||||
 | 
						codec_init(codec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (payload_type != PTYPE_UNDEFINED) {
 | 
				
			||||||
 | 
							/* Make sure we do not get any reserved or undefined type numbers */
 | 
				
			||||||
 | 
							/* See also: https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml */
 | 
				
			||||||
 | 
							if ((payload_type == 1 || payload_type == 2 || payload_type == 19)
 | 
				
			||||||
 | 
							    || (payload_type >= 72 && payload_type <= 76)
 | 
				
			||||||
 | 
							    || (payload_type >= 127)) {
 | 
				
			||||||
 | 
								LOGP(DLMGCP, LOGL_ERROR, "Cannot add codec, payload type number %d is reserved\n",
 | 
				
			||||||
 | 
								     payload_type);
 | 
				
			||||||
 | 
								goto error;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							codec->payload_type = payload_type;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* When no audio name is given, we are forced to use the payload
 | 
				
			||||||
 | 
						 * type to generate the audio name. This is only possible for
 | 
				
			||||||
 | 
						 * non dynamic payload types, which are statically defined */
 | 
				
			||||||
 | 
						if (!audio_name) {
 | 
				
			||||||
 | 
							switch (payload_type) {
 | 
				
			||||||
 | 
							case 0:
 | 
				
			||||||
 | 
								strcpy(codec->audio_name, "PCMU/8000/1");
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 3:
 | 
				
			||||||
 | 
								strcpy(codec->audio_name, "GSM/8000/1");
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 8:
 | 
				
			||||||
 | 
								strcpy(codec->audio_name, "PCMA/8000/1");
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 18:
 | 
				
			||||||
 | 
								strcpy(codec->audio_name, "G729/8000/1");
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								/* The given payload type is not known to us, or it
 | 
				
			||||||
 | 
								 * it is a dynamic payload type for which we do not
 | 
				
			||||||
 | 
								 * know the audio name. We must give up here */
 | 
				
			||||||
 | 
								LOGP(DLMGCP, LOGL_ERROR, "No audio codec name given, and payload type %d unknown\n",
 | 
				
			||||||
 | 
								     payload_type);
 | 
				
			||||||
 | 
								goto error;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							OSMO_STRLCPY_ARRAY(codec->audio_name, audio_name);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Now we extract the codec subtype name, rate and channels. The latter
 | 
				
			||||||
 | 
						 * two are optional. If they are not present we use the safe defaults
 | 
				
			||||||
 | 
						 * above. */
 | 
				
			||||||
 | 
						if (strlen(codec->audio_name) >= sizeof(codec->subtype_name)) {
 | 
				
			||||||
 | 
							LOGP(DLMGCP, LOGL_ERROR, "Audio codec too long: %s\n", osmo_quote_str(codec->audio_name, -1));
 | 
				
			||||||
 | 
							goto error;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						channels = DEFAULT_RTP_AUDIO_DEFAULT_CHANNELS;
 | 
				
			||||||
 | 
						rate = DEFAULT_RTP_AUDIO_DEFAULT_RATE;
 | 
				
			||||||
 | 
						if (sscanf(codec->audio_name, "%63[^/]/%d/%d", codec->subtype_name, &rate, &channels) < 1) {
 | 
				
			||||||
 | 
							LOGP(DLMGCP, LOGL_ERROR, "Invalid audio codec: %s\n", osmo_quote_str(codec->audio_name, -1));
 | 
				
			||||||
 | 
							goto error;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Note: We only accept configurations with one audio channel! */
 | 
				
			||||||
 | 
						if (channels != 1) {
 | 
				
			||||||
 | 
							LOGP(DLMGCP, LOGL_ERROR, "Cannot handle audio codec with more than one channel: %s\n",
 | 
				
			||||||
 | 
							     osmo_quote_str(codec->audio_name, -1));
 | 
				
			||||||
 | 
							goto error;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						codec->rate = rate;
 | 
				
			||||||
 | 
						codec->channels = channels;
 | 
				
			||||||
 | 
						codec->payload_type = payload_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!strcmp(codec->subtype_name, "G729")) {
 | 
				
			||||||
 | 
							codec->frame_duration_num = 10;
 | 
				
			||||||
 | 
							codec->frame_duration_den = 1000;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							codec->frame_duration_num = DEFAULT_RTP_AUDIO_FRAME_DUR_NUM;
 | 
				
			||||||
 | 
							codec->frame_duration_den = DEFAULT_RTP_AUDIO_FRAME_DUR_DEN;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Derive the payload type if it is unknown */
 | 
				
			||||||
 | 
						if (codec->payload_type == PTYPE_UNDEFINED) {
 | 
				
			||||||
 | 
							/* TODO: This is semi dead code, see OS#4150 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* For the known codecs from the static range we restore
 | 
				
			||||||
 | 
							 * the IANA or 3GPP assigned payload type number */
 | 
				
			||||||
 | 
							if (codec->rate == 8000 && codec->channels == 1) {
 | 
				
			||||||
 | 
								/* See also: https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml */
 | 
				
			||||||
 | 
								if (!strcmp(codec->subtype_name, "GSM"))
 | 
				
			||||||
 | 
									codec->payload_type = 3;
 | 
				
			||||||
 | 
								else if (!strcmp(codec->subtype_name, "PCMA"))
 | 
				
			||||||
 | 
									codec->payload_type = 8;
 | 
				
			||||||
 | 
								else if (!strcmp(codec->subtype_name, "PCMU"))
 | 
				
			||||||
 | 
									codec->payload_type = 0;
 | 
				
			||||||
 | 
								else if (!strcmp(codec->subtype_name, "G729"))
 | 
				
			||||||
 | 
									codec->payload_type = 18;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* See also: 3GPP TS 48.103, chapter 5.4.2.2 RTP Payload
 | 
				
			||||||
 | 
								 * Note: These are not fixed payload types as the IANA
 | 
				
			||||||
 | 
								 * defined once, they still remain dymanic payload
 | 
				
			||||||
 | 
								 * types, but with a payload type number preference. */
 | 
				
			||||||
 | 
								else if (!strcmp(codec->subtype_name, "GSM-EFR"))
 | 
				
			||||||
 | 
									codec->payload_type = 110;
 | 
				
			||||||
 | 
								else if (!strcmp(codec->subtype_name, "GSM-HR-08"))
 | 
				
			||||||
 | 
									codec->payload_type = 111;
 | 
				
			||||||
 | 
								else if (!strcmp(codec->subtype_name, "AMR"))
 | 
				
			||||||
 | 
									codec->payload_type = 112;
 | 
				
			||||||
 | 
								else if (!strcmp(codec->subtype_name, "AMR-WB"))
 | 
				
			||||||
 | 
									codec->payload_type = 113;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* If we could not determine a payload type we assume that
 | 
				
			||||||
 | 
							 * we are dealing with a codec from the dynamic range. We
 | 
				
			||||||
 | 
							 * choose a fixed identifier from 96-109. (Note: normally,
 | 
				
			||||||
 | 
							 * the dynamic payload type rante is from 96-127, but from
 | 
				
			||||||
 | 
							 * 110 onwards 3gpp defines prefered codec types, which are
 | 
				
			||||||
 | 
							 * also fixed, see above)  */
 | 
				
			||||||
 | 
							if (codec->payload_type < 0) {
 | 
				
			||||||
 | 
								/* FIXME: pt_offset is completely unrelated and useless here, any of those numbers may already
 | 
				
			||||||
 | 
								 * have been added to the codecs. Instead, there should be an iterator checking for an actually
 | 
				
			||||||
 | 
								 * unused dynamic payload type number. */
 | 
				
			||||||
 | 
								codec->payload_type = 96 + pt_offset;
 | 
				
			||||||
 | 
								if (codec->payload_type > 109) {
 | 
				
			||||||
 | 
									LOGP(DLMGCP, LOGL_ERROR, "Ran out of payload type numbers to assign dynamically\n");
 | 
				
			||||||
 | 
									goto error;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Copy over optional codec parameters */
 | 
				
			||||||
 | 
						if (param) {
 | 
				
			||||||
 | 
							codec->param = *param;
 | 
				
			||||||
 | 
							codec->param_present = true;
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							codec->param_present = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						conn->end.codecs_assigned++;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					error:
 | 
				
			||||||
 | 
						/* Make sure we leave a clean codec entry on error. */
 | 
				
			||||||
 | 
						codec_free(codec);
 | 
				
			||||||
 | 
						return -EINVAL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Check if the given codec is applicable on the specified endpoint
 | 
				
			||||||
 | 
					 * Helper function for mgcp_codec_decide() */
 | 
				
			||||||
 | 
					static bool is_codec_compatible(const struct mgcp_endpoint *endp, const struct mgcp_rtp_codec *codec)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/* A codec name must be set, if not, this might mean that the codec
 | 
				
			||||||
 | 
						 * (payload type) that was assigned is unknown to us so we must stop
 | 
				
			||||||
 | 
						 * here. */
 | 
				
			||||||
 | 
						if (!strlen(codec->subtype_name))
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* FIXME: implement meaningful checks to make sure that the given codec
 | 
				
			||||||
 | 
						 * is compatible with the given endpoint */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! Decide for one suitable codec
 | 
				
			||||||
 | 
					 *  \param[in] conn related rtp-connection.
 | 
				
			||||||
 | 
					 *  \returns 0 on success, -EINVAL on failure. */
 | 
				
			||||||
 | 
					int mgcp_codec_decide(struct mgcp_conn_rtp *conn)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mgcp_rtp_end *rtp;
 | 
				
			||||||
 | 
						unsigned int i;
 | 
				
			||||||
 | 
						struct mgcp_endpoint *endp;
 | 
				
			||||||
 | 
						bool codec_assigned = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						endp = conn->conn->endp;
 | 
				
			||||||
 | 
						rtp = &conn->end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* This function works on the results the SDP/LCO parser has extracted
 | 
				
			||||||
 | 
						 * from the MGCP message. The goal is to select a suitable codec for
 | 
				
			||||||
 | 
						 * the given connection. When transcoding is available, the first codec
 | 
				
			||||||
 | 
						 * from the codec list is taken without further checking. When
 | 
				
			||||||
 | 
						 * transcoding is not available, then the choice must be made more
 | 
				
			||||||
 | 
						 * carefully. Each codec in the list is checked until one is found that
 | 
				
			||||||
 | 
						 * is rated compatible. The rating is done by the helper function
 | 
				
			||||||
 | 
						 * is_codec_compatible(), which does the actual checking. */
 | 
				
			||||||
 | 
						for (i = 0; i < rtp->codecs_assigned; i++) {
 | 
				
			||||||
 | 
							/* When no transcoding is available, avoid codecs that would
 | 
				
			||||||
 | 
							 * require transcoding. */
 | 
				
			||||||
 | 
							if (endp->trunk->no_audio_transcoding && !is_codec_compatible(endp, &rtp->codecs[i])) {
 | 
				
			||||||
 | 
								LOGP(DLMGCP, LOGL_NOTICE, "transcoding not available, skipping codec: %d/%s\n",
 | 
				
			||||||
 | 
								     rtp->codecs[i].payload_type, rtp->codecs[i].subtype_name);
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							rtp->codec = &rtp->codecs[i];
 | 
				
			||||||
 | 
							codec_assigned = true;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* FIXME: To the reviewes: This is problematic. I do not get why we
 | 
				
			||||||
 | 
						 * need to reset the packet_duration_ms depending on the codec
 | 
				
			||||||
 | 
						 * selection. I thought it were all 20ms? Is this to address some
 | 
				
			||||||
 | 
						 * cornercase. (This piece of code was in the code path before,
 | 
				
			||||||
 | 
						 * together with the note: "TODO/XXX: Store this per codec and derive
 | 
				
			||||||
 | 
						 * it on use" */
 | 
				
			||||||
 | 
						if (codec_assigned) {
 | 
				
			||||||
 | 
							if (rtp->maximum_packet_time >= 0
 | 
				
			||||||
 | 
							    && rtp->maximum_packet_time * rtp->codec->frame_duration_den >
 | 
				
			||||||
 | 
							    rtp->codec->frame_duration_num * 1500)
 | 
				
			||||||
 | 
								rtp->packet_duration_ms = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return -EINVAL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Return true if octet-aligned is set in the given codec. Default to octet-aligned=0, i.e. bandwidth-efficient mode.
 | 
				
			||||||
 | 
					 * See RFC4867 "RTP Payload Format for AMR and AMR-WB" sections "8.1. AMR Media Type Registration" and "8.2. AMR-WB
 | 
				
			||||||
 | 
					 * Media Type Registration":
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *    octet-align: Permissible values are 0 and 1.  If 1, octet-aligned
 | 
				
			||||||
 | 
					 *                 operation SHALL be used.  If 0 or if not present,
 | 
				
			||||||
 | 
					 *                 bandwidth-efficient operation is employed.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * https://tools.ietf.org/html/rfc4867
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static bool amr_is_octet_aligned(const struct mgcp_rtp_codec *codec)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!codec->param_present)
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						if (!codec->param.amr_octet_aligned_present)
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						return codec->param.amr_octet_aligned;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Compare two codecs, all parameters must match up, except for the payload type
 | 
				
			||||||
 | 
					 * number. */
 | 
				
			||||||
 | 
					static bool codecs_same(struct mgcp_rtp_codec *codec_a, struct mgcp_rtp_codec *codec_b)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (codec_a->rate != codec_b->rate)
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						if (codec_a->channels != codec_b->channels)
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						if (codec_a->frame_duration_num != codec_b->frame_duration_num)
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						if (codec_a->frame_duration_den != codec_b->frame_duration_den)
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						if (strcmp(codec_a->subtype_name, codec_b->subtype_name))
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						if (!strcmp(codec_a->subtype_name, "AMR")) {
 | 
				
			||||||
 | 
							if (amr_is_octet_aligned(codec_a) != amr_is_octet_aligned(codec_b))
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! Translate a given payload type number that belongs to the packet of a
 | 
				
			||||||
 | 
					 *  source connection to the equivalent payload type number that matches the
 | 
				
			||||||
 | 
					 *  configuration of a destination connection.
 | 
				
			||||||
 | 
					 *  \param[in] conn_src related source rtp-connection.
 | 
				
			||||||
 | 
					 *  \param[in] conn_dst related destination rtp-connection.
 | 
				
			||||||
 | 
					 *  \param[in] payload_type number from the source packet or source connection.
 | 
				
			||||||
 | 
					 *  \returns translated payload type number on success, -EINVAL on failure. */
 | 
				
			||||||
 | 
					int mgcp_codec_pt_translate(struct mgcp_conn_rtp *conn_src, struct mgcp_conn_rtp *conn_dst, int payload_type)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mgcp_rtp_end *rtp_src;
 | 
				
			||||||
 | 
						struct mgcp_rtp_end *rtp_dst;
 | 
				
			||||||
 | 
						struct mgcp_rtp_codec *codec_src = NULL;
 | 
				
			||||||
 | 
						struct mgcp_rtp_codec *codec_dst = NULL;
 | 
				
			||||||
 | 
						unsigned int i;
 | 
				
			||||||
 | 
						unsigned int codecs_assigned;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rtp_src = &conn_src->end;
 | 
				
			||||||
 | 
						rtp_dst = &conn_dst->end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Find the codec information that is used on the source side */
 | 
				
			||||||
 | 
						codecs_assigned = rtp_src->codecs_assigned;
 | 
				
			||||||
 | 
						OSMO_ASSERT(codecs_assigned <= MGCP_MAX_CODECS);
 | 
				
			||||||
 | 
						for (i = 0; i < codecs_assigned; i++) {
 | 
				
			||||||
 | 
							if (payload_type == rtp_src->codecs[i].payload_type) {
 | 
				
			||||||
 | 
								codec_src = &rtp_src->codecs[i];
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (!codec_src)
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Use the codec infrmation from the source and try to find the
 | 
				
			||||||
 | 
						 * equivalent of it on the destination side */
 | 
				
			||||||
 | 
						codecs_assigned = rtp_dst->codecs_assigned;
 | 
				
			||||||
 | 
						OSMO_ASSERT(codecs_assigned <= MGCP_MAX_CODECS);
 | 
				
			||||||
 | 
						for (i = 0; i < codecs_assigned; i++) {
 | 
				
			||||||
 | 
							if (codecs_same(codec_src, &rtp_dst->codecs[i])) {
 | 
				
			||||||
 | 
								codec_dst = &rtp_dst->codecs[i];
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (!codec_dst)
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return codec_dst->payload_type;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Find the payload type number configured for a specific codec by SDP.
 | 
				
			||||||
 | 
					 * For example, IuUP gets assigned a payload type number, and the endpoint needs to translate that to the number
 | 
				
			||||||
 | 
					 * assigned to "AMR" on the other conn (by a=rtpmap:N).
 | 
				
			||||||
 | 
					 * \param conn  The side of an endpoint to get the payload type number for (to translate the payload type number to).
 | 
				
			||||||
 | 
					 * \param subtype_name  SDP codec name without parameters (e.g. "AMR").
 | 
				
			||||||
 | 
					 * \param match_nr  Index for the match found, first being match_nr == 0. Iterate all matches by calling multiple times
 | 
				
			||||||
 | 
					 *                  with incrementing match_nr.
 | 
				
			||||||
 | 
					 * \return codec definition for that conn matching the subtype_name, or NULL if no such match_nr is found.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const struct mgcp_rtp_codec *mgcp_codec_pt_find_by_subtype_name(struct mgcp_conn_rtp *conn,
 | 
				
			||||||
 | 
													const char *subtype_name, unsigned int match_nr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						for (i = 0; i < conn->end.codecs_assigned; i++) {
 | 
				
			||||||
 | 
							if (!strcmp(conn->end.codecs[i].subtype_name, subtype_name)) {
 | 
				
			||||||
 | 
								if (match_nr) {
 | 
				
			||||||
 | 
									match_nr--;
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return &conn->end.codecs[i];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user