blob: 4e2b803f7c0a6e607795dc7a4cdfbdf8d2c51bcb [file] [log] [blame]
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +08001/* Use the UniPorte library to allocate endpoints */
2/*
Holger Hans Peter Freyther1cf3a832011-01-26 12:51:22 +01003 * (C) 2010-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
4 * (C) 2010-2011 by On-Waves
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +08005 * All Rights Reserved
6 *
Holger Hans Peter Freytherde56c222011-01-16 17:45:14 +01007 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080010 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Holger Hans Peter Freytherde56c222011-01-16 17:45:14 +010015 * GNU Affero General Public License for more details.
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080016 *
Holger Hans Peter Freytherde56c222011-01-16 17:45:14 +010017 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080019 *
20 */
21
22#include <mgcp_ss7.h>
23#include <mgcp/mgcp.h>
24#include <mgcp/mgcp_internal.h>
25
Holger Hans Peter Freythercbf7d182010-07-31 05:25:35 +080026#include <cellmgr_debug.h>
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080027
Holger Hans Peter Freytherc21c0d62011-07-22 09:00:23 +020028#include <osmocom/core/application.h>
Harald Welteff397ed2011-05-08 10:29:23 +020029#include <osmocom/core/select.h>
30#include <osmocom/core/talloc.h>
31#include <osmocom/core/timer.h>
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080032
Holger Hans Peter Freythercbf7d182010-07-31 05:25:35 +080033#include <osmocom/vty/vty.h>
Holger Hans Peter Freythercc1a9382010-08-04 06:24:04 +080034#include <osmocom/vty/telnet_interface.h>
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080035
36/* uniporte includes */
37#ifndef NO_UNIPORTE
38#include <UniPorte.h>
39#include <BusMastHostApi.h>
40#include <MtnSa.h>
41#include <SystemLayer.h>
42#include <PredefMobs.h>
43#endif
44
45#include <errno.h>
46#include <limits.h>
47#include <string.h>
48#include <unistd.h>
49#include <signal.h>
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080050
51#ifndef _GNU_SOURCE
52#define _GNU_SOURCE
53#endif
54#include <getopt.h>
55
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080056static char *config_file = "mgcp_mgw.cfg";
57static int exit_on_failure = 0;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080058
Holger Hans Peter Freyther1cf3a832011-01-26 12:51:22 +010059
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +010060extern struct mgcp_config *g_cfg;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080061
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +010062static void mgcp_ss7_endp_free(struct mgcp_endpoint *endp);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080063
Holger Hans Peter Freyther8fa8e582010-12-01 23:14:57 +010064
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +010065#ifndef NO_UNIPORTE
66static void mgcp_ss7_do_exec(struct mgcp_ss7 *mgcp, uint8_t type, struct mgcp_endpoint *, uint32_t param);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080067
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +010068/* Contains a mapping from UniPorte to the MGCP side of things */
69static struct mgcp_endpoint *s_endpoints[240];
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080070
Holger Hans Peter Freyther672f3212011-03-01 13:52:57 +010071static int select_voice_port(struct mgcp_endpoint *endp)
72{
73 int mgw_port;
74 int timeslot, multiplex;
75
76 mgcp_endpoint_to_timeslot(ENDPOINT_NUMBER(endp), &multiplex, &timeslot);
Holger Hans Peter Freyther3c8b0f82011-03-02 22:22:50 +010077 if (endp->blocked) {
78 LOGP(DMGCP, LOGL_ERROR, "Timeslot 0x%x is blocked.\n", timeslot);
Holger Hans Peter Freyther672f3212011-03-01 13:52:57 +010079 return -1;
80 }
81
Holger Hans Peter Freythere72139a2011-09-13 22:41:48 +020082 mgw_port = endp->hw_snmp_port - 1;
Holger Hans Peter Freyther672f3212011-03-01 13:52:57 +010083 fprintf(stderr, "TEST: Going to use MGW: %d for MUL: %d TS: %d\n",
84 mgw_port, multiplex, timeslot);
85 return mgw_port;
86}
87
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080088static void check_exit(int status)
89{
90 if (exit_on_failure && status == 21) {
91 LOGP(DMGCP, LOGL_ERROR, "Failure detected with the MGW. Exiting.\n");
92 exit(-1);
93 }
94}
95
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +010096
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080097static void Force_Poll( int milliseconds )
98{
99 int timeout = 0;
100 unsigned long startTime;
101
102 startTime = SysLyrGetTime();
103
104 /* Loop until the specified number of milliseconds
105 * have elapsed.
106 */
107 do {
108 MtnSaPoll();
109 SysLyrSleep( 20 );
110 } while ((SysLyrGetTime()-startTime)<(unsigned long)milliseconds);
111 return;
112}
113
114static char eventName[Event_TELEMETRY_DATA + 1][128] = {
115 { "Event_NOT_READY" },
116 { "Event_READY" },
117 { "Event_ANSWER" },
118 { "Event_OUTGOING_CALL" },
119 { "Event_ABORT" },
120 { "Event_CONNECT" },
121 { "Event_DISCONNECT" },
122 { "Event_MANAGED_OBJECT_GET_COMPLETE" },
123 { "Event_MANAGED_OBJECT_GET_AND_CLEAR_COMPLETE" },
124 { "Event_MANAGED_OBJECT_SET_COMPLETE" },
125 { "Event_MANAGED_OBJECT_TRAP" },
126 { "Event_PREDEF_MOB_SET_COMPLETE" },
127 { "Event_PREDEF_MOB_GET_COMPLETE" },
128 { "Event_USER_MOB_DEFINE_COMPLETE" },
129 { "Event_USER_MOB_SET_COMPLETE" },
130 { "Event_USER_MOB_GET_COMPLETE" },
131 { "Event_RECEIVE_DATA" },
132 { "Event_SEND_COMPLETE" },
133 { "Event_TDM_CONNECT_COMPLETE" },
134 { "Event_LOG" },
135 { "Event_DEVICE_IN_CONTACT" },
136 { "Event_DEVICE_MANAGED" },
137 { "Event_DEVICE_OUT_OF_CONTACT" },
138 { "Event_TELEMETRY_DATA" } };
139
140static char stateName[PortState_END_OF_ENUM][128] = {
141 { "PortState_IDLE" },
142 { "PortState_SIGNALING" },
143 { "PortState_INITIATING" },
144 { "PortState_LINK" },
145 { "PortState_TRAINING" },
146 { "PortState_EC_NEGOTIATING" },
147 { "PortState_DATA" },
148 { "PortState_RESYNCING" },
149 { "PortState_FAX" },
150 { "PortState_COMMAND_ESCAPE" },
151 { "PortState_TERMINATING" },
152 { "PortState_VOICE" },
153 { "PortState_PORT_RESET" },
154 { "PortState_DSP_RESET" },
155 { "PortState_ALLOCATED" },
156 { "PortState_OUT_OF_SERVICE" },
157 { "PortState_RECONFIGURE" },
158 { "PortState_ON_HOLD" } };
159static int uniporte_events(unsigned long port, EventTypeT event,
160 void *event_data, unsigned long event_data_length ) {
161 char text[128];
162 ManObjectInfoPtr info;
163 DataReceiveInfoPtr dataInfo;
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100164 struct mgcp_endpoint *endp;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800165 int i;
166 ToneDetectionPtr tones;
167
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800168 /* Don't print output when we receive data or complete
169 * sending data. That would be too verbose.
170 */
171 if (event==Event_DEVICE_MANAGED) {
172 MtnSaSetManObject(0, ChannelType_ETHERNET, ManObj_C_MOE_COMM_LOSS_RESET_DELAY ,
173 10, 0);
174 }
175 else if (event==Event_MANAGED_OBJECT_TRAP ) {
176 info = (ManObjectInfoPtr)event_data;
177 if (info->trapId == Trap_PORT_STATE_CHANGE) {
178 sprintf(text, "Port #%ld, Change to state %s", port, stateName[info->value]);
179 puts(text);
180
181 /* update the mgcp state */
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100182 if (port >= ARRAY_SIZE(s_endpoints)) {
183 fprintf(stderr, "The port is bigger than we can manage.\n");
184 return 0;
185 }
186
187 endp = s_endpoints[port];
188 if (!endp) {
189 fprintf(stderr, "Unexpected event on port %d\n", port);
190 return 0;
191 }
192
193 if (endp->block_processing != 1)
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800194 fprintf(stderr, "State change on a non blocked port. ERROR.\n");
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100195 endp->block_processing = 0;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800196 }
197 }
198 else if ( event == Event_MANAGED_OBJECT_SET_COMPLETE ) {
199 info = (ManObjectInfoPtr)event_data;
200
201 sprintf(text, "Object %d value %d status %d", info->object, info->value,
202 info->status );
203 puts(text);
204 check_exit(info->status);
205 }
206 else if ( ( event == Event_USER_MOB_SET_COMPLETE ) ||
207 ( event == Event_USER_MOB_DEFINE_COMPLETE ) )
208 {
209 info = (ManObjectInfoPtr)event_data;
210
211 sprintf( text, "Mob ID %d status %d", info->MOBId, info->status );
212 puts(text);
213 check_exit(info->status);
214 }
215 else if ( event == Event_USER_MOB_GET_COMPLETE )
216 {
217 info = (ManObjectInfoPtr)event_data;
218
219 sprintf( text, "Mob ID %d status %d", info->MOBId, info->status );
220 puts(text);
221 check_exit(info->status);
222 }
223 else if (event == Event_CONNECT)
224 {
225 sprintf(text, "Port %d connected",port );
226 }
227 else if (event == Event_PREDEF_MOB_GET_COMPLETE)
228 {
229 info = (ManObjectInfoPtr)event_data;
230
231 sprintf(text, "Mob ID %d status %d", info->MOBId, info->status );
232 puts(text);
233 check_exit(info->status);
234 }
235
236 return( 0 );
237}
238
239static int initialize_uniporte(struct mgcp_ss7 *mgcp)
240{
241 ProfileT profile;
242 unsigned long mgw_address;
243 int rc;
244
245 LOGP(DMGCP, LOGL_NOTICE, "Initializing MGW on %s\n", mgcp->cfg->bts_ip);
246
247 MtnSaSetEthernetOnly();
248 rc = MtnSaStartup(uniporte_events);
249 if (rc != 0)
250 LOGP(DMGCP, LOGL_ERROR, "Failed to startup the MGW.\n");
251 SysEthGetHostAddress(mgcp->cfg->bts_ip, &mgw_address);
252 rc = MtnSaRegisterEthernetDevice(mgw_address, 0);
253 if (rc != 0)
254 LOGP(DMGCP, LOGL_ERROR, "Failed to register ethernet.\n");
255 Force_Poll(2000);
256 MtnSaTakeOverDevice(0);
257 Force_Poll(2000);
258 MtnSaSetReceiveTraps(1);
259 MtnSaSetTransparent();
260
261 /* change the voice profile to AMR */
262 MtnSaGetProfile(ProfileType_VOICE, 0, &profile);
263 profile.countryCode = CountryCode_INTERNAT_ALAW;
264 MtnSaSetProfile(ProfileType_VOICE, 0, &profile);
265
266 if (MtnSaGetPortCount() == 0)
267 return -1;
268
269 return 0;
270}
271
272
273static void* start_uniporte(void *_ss7) {
274 struct llist_head blocked;
275 struct mgcp_ss7_cmd *cmd, *tmp;
276 struct mgcp_ss7 *ss7 = _ss7;
277
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800278 if (initialize_uniporte(ss7) != 0) {
279 fprintf(stderr, "Failed to create Uniporte.\n");
280 exit(-1);
281 return 0;
282 }
283
284 fprintf(stderr, "Created the MGCP processing thread.\n");
285 INIT_LLIST_HEAD(&blocked);
286 for (;;) {
287 thread_swap(ss7->cmd_queue);
288start_over:
289 /* handle items that are currently blocked */
290 llist_for_each_entry_safe(cmd, tmp, &blocked, entry) {
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100291 if (cmd->endp->block_processing)
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800292 continue;
293
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100294 mgcp_ss7_do_exec(ss7, cmd->type, cmd->endp, cmd->param);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800295 llist_del(&cmd->entry);
296 free(cmd);
297
298 /* We might have unblocked something, make sure we operate in order */
299 MtnSaPoll();
300 goto start_over;
301 }
302
303 llist_for_each_entry_safe(cmd, tmp, ss7->cmd_queue->main_head, entry) {
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100304 if (cmd->endp->block_processing) {
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800305 llist_del(&cmd->entry);
306 llist_add_tail(&cmd->entry, &blocked);
307 continue;
308 }
309
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100310 mgcp_ss7_do_exec(ss7, cmd->type, cmd->endp, cmd->param);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800311 llist_del(&cmd->entry);
312 free(cmd);
313
314 /* We might have unblocked something, make sure we operate in order */
315 MtnSaPoll();
316 goto start_over;
317 }
318
319 Force_Poll(20);
320 }
321
322 return 0;
323}
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800324
325static void update_mute_status(int mgw_port, int conn_mode)
326{
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800327 if (conn_mode == MGCP_CONN_NONE) {
328 MtnSaSetManObject(mgw_port, ChannelType_PORT, ManObj_C_VOICE_UPSTREAM_MUTE, 1, 0);
329 MtnSaSetManObject(mgw_port, ChannelType_PORT, ManObj_C_VOICE_DOWNSTREAM_MUTE, 1, 0);
330 } else if (conn_mode == MGCP_CONN_RECV_ONLY) {
331 MtnSaSetManObject(mgw_port, ChannelType_PORT, ManObj_C_VOICE_UPSTREAM_MUTE, 1, 0);
332 MtnSaSetManObject(mgw_port, ChannelType_PORT, ManObj_C_VOICE_DOWNSTREAM_MUTE, 0, 0);
333 } else if (conn_mode == MGCP_CONN_SEND_ONLY) {
334 MtnSaSetManObject(mgw_port, ChannelType_PORT, ManObj_C_VOICE_UPSTREAM_MUTE, 0, 0);
335 MtnSaSetManObject(mgw_port, ChannelType_PORT, ManObj_C_VOICE_DOWNSTREAM_MUTE, 1, 0);
336 } else if (conn_mode == MGCP_CONN_RECV_SEND) {
337 MtnSaSetManObject(mgw_port, ChannelType_PORT, ManObj_C_VOICE_UPSTREAM_MUTE, 0, 0);
338 MtnSaSetManObject(mgw_port, ChannelType_PORT, ManObj_C_VOICE_DOWNSTREAM_MUTE, 0, 0);
339 } else {
340 LOGP(DMGCP, LOGL_ERROR, "Unhandled conn mode: %d\n", conn_mode);
341 }
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800342}
343
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100344static void allocate_endp(struct mgcp_ss7 *ss7, struct mgcp_endpoint *endp)
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800345{
Holger Hans Peter Freyther672f3212011-03-01 13:52:57 +0100346 int mgw_port;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800347 unsigned long mgw_address, loc_address;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800348
Holger Hans Peter Freyther672f3212011-03-01 13:52:57 +0100349 /* now find the voice processor we want to use */
350 mgw_port = select_voice_port(endp);
351 if (mgw_port < 0)
352 return;
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100353
354 endp->audio_port = MtnSaAllocate(mgw_port);
355 if (endp->audio_port == UINT_MAX) {
356 fprintf(stderr, "Failed to allocate the port: %d\n", ENDPOINT_NUMBER(endp));
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800357 return;
358 }
359
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100360 if (mgw_port != endp->audio_port) {
361 fprintf(stderr, "Oh... a lot of assumptions are now broken %d %d %s:%d\n",
362 mgw_port, endp->audio_port, __func__, __LINE__);
363 }
364
365 s_endpoints[endp->audio_port] = endp;
366
Holger Hans Peter Freyther8fa8e582010-12-01 23:14:57 +0100367 /* Gain settings, apply before switching the port to voice */
368 MtnSaSetManObject(mgw_port, ChannelType_PORT,
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100369 ManObj_C_VOICE_INPUT_DIGITAL_GAIN, endp->tcfg->digital_inp_gain, 0);
Holger Hans Peter Freyther8fa8e582010-12-01 23:14:57 +0100370 MtnSaSetManObject(mgw_port, ChannelType_PORT,
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100371 ManObj_C_VOICE_OUTPUT_DIGITAL_GAIN, endp->tcfg->digital_out_gain, 0);
Holger Hans Peter Freyther8fa8e582010-12-01 23:14:57 +0100372 MtnSaSetManObject(mgw_port, ChannelType_PORT,
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100373 ManObj_G_US_AGC_ENABLE, endp->tcfg->upstr_agc_enbl, 0);
Holger Hans Peter Freyther8fa8e582010-12-01 23:14:57 +0100374 MtnSaSetManObject(mgw_port, ChannelType_PORT,
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100375 ManObj_G_DS_AGC_ENABLE, endp->tcfg->dwnstr_agc_enbl, 0);
Holger Hans Peter Freyther8fa8e582010-12-01 23:14:57 +0100376 MtnSaSetManObject(mgw_port, ChannelType_PORT,
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100377 ManObj_G_US_ADAPTATION_RATE, endp->tcfg->upstr_adp_rate, 0);
Holger Hans Peter Freyther8fa8e582010-12-01 23:14:57 +0100378 MtnSaSetManObject(mgw_port, ChannelType_PORT,
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100379 ManObj_G_DS_ADAPTATION_RATE, endp->tcfg->dwnstr_adp_rate, 0);
Holger Hans Peter Freyther8fa8e582010-12-01 23:14:57 +0100380 MtnSaSetManObject(mgw_port, ChannelType_PORT,
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100381 ManObj_G_US_MAX_APPLIED_GAIN, endp->tcfg->upstr_max_gain, 0);
Holger Hans Peter Freyther8fa8e582010-12-01 23:14:57 +0100382 MtnSaSetManObject(mgw_port, ChannelType_PORT,
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100383 ManObj_G_DS_MAX_APPLIED_GAIN, endp->tcfg->dwnstr_max_gain, 0);
Holger Hans Peter Freyther8fa8e582010-12-01 23:14:57 +0100384 MtnSaSetManObject(mgw_port, ChannelType_PORT,
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100385 ManObj_C_US_TARGET_LEVEL, endp->tcfg->upstr_target_lvl, 0);
Holger Hans Peter Freyther8fa8e582010-12-01 23:14:57 +0100386 MtnSaSetManObject(mgw_port, ChannelType_PORT,
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100387 ManObj_C_US_TARGET_LEVEL, endp->tcfg->dwnstr_target_lvl, 0);
Holger Hans Peter Freyther8fa8e582010-12-01 23:14:57 +0100388
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800389 /* Select AMR 5.9, Payload 98, no CRC, hardcoded */
390 MtnSaApplyProfile(mgw_port, ProfileType_VOICE, 0);
391 MtnSaSetManObject(mgw_port, ChannelType_PORT,
392 ManObj_G_DATA_PATH, DataPathT_ETHERNET, 0 );
393 MtnSaSetManObject(mgw_port, ChannelType_PORT,
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100394 ManObj_C_VOICE_RTP_TELEPHONE_EVENT_PT_TX,
395 endp->tcfg->audio_payload, 0);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800396 MtnSaSetManObject(mgw_port, ChannelType_PORT,
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100397 ManObj_G_RTP_AMR_PAYLOAD_TYPE,
398 endp->tcfg->audio_payload, 0);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800399 MtnSaSetManObject(mgw_port, ChannelType_PORT,
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100400 ManObj_G_RTP_AMR_PAYLOAD_FORMAT,
401 RtpAmrPayloadFormat_OCTET_ALIGNED, 0);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800402 MtnSaSetManObject(mgw_port, ChannelType_PORT,
403 ManObj_G_VOICE_ENCODING, Voice_Encoding_AMR_5_90, 0);
Holger Hans Peter Freytherd5918ff2010-08-06 16:03:27 +0000404 MtnSaSetManObject(mgw_port, ChannelType_PORT,
Holger Hans Peter Freytheredfadae2011-04-26 18:19:14 +0200405 ManObj_C_AMR_MODE_CHANGE, 2, 0);
406 MtnSaSetManObject(mgw_port, ChannelType_PORT,
407 ManObj_C_AMR_MODE_REQUEST, 2, 0);
408 MtnSaSetManObject(mgw_port, ChannelType_PORT,
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100409 ManObj_C_VOICE_VAD_CNG, endp->tcfg->vad_enabled, 0);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800410
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100411 update_mute_status(mgw_port, endp->conn_mode);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800412
413 /* set the addresses */
414 SysEthGetHostAddress(ss7->cfg->bts_ip, &mgw_address);
415 SysEthGetHostAddress(ss7->cfg->local_ip, &loc_address);
416 MtnSaSetVoIpAddresses(mgw_port,
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100417 mgw_address, endp->bts_end.local_port,
418 loc_address, endp->bts_end.local_port);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800419 MtnSaConnect(mgw_port, mgw_port);
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100420 endp->block_processing = 1;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800421}
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800422
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100423static void mgcp_ss7_do_exec(struct mgcp_ss7 *mgcp, uint8_t type,
424 struct mgcp_endpoint *mgw_endp, uint32_t param)
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800425{
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800426 int rc;
427
428 switch (type) {
429 case MGCP_SS7_MUTE_STATUS:
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100430 if (mgw_endp->audio_port != UINT_MAX)
431 update_mute_status(mgw_endp->audio_port, param);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800432 break;
433 case MGCP_SS7_DELETE:
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100434 if (mgw_endp->audio_port != UINT_MAX) {
435 rc = MtnSaDisconnect(mgw_endp->audio_port);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800436 if (rc != 0)
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100437 fprintf(stderr, "Failed to disconnect port: %u\n", mgw_endp->audio_port);
438 rc = MtnSaDeallocate(mgw_endp->audio_port);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800439 if (rc != 0)
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100440 fprintf(stderr, "Failed to deallocate port: %u\n", mgw_endp->audio_port);
441
442 mgw_endp->audio_port = UINT_MAX;
443 mgw_endp->block_processing = 1;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800444 }
445 break;
446 case MGCP_SS7_ALLOCATE:
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100447 allocate_endp(mgcp, mgw_endp);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800448 break;
449 }
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800450}
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100451#endif
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800452
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100453void mgcp_ss7_exec(struct mgcp_endpoint *endp, int type, uint32_t param)
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800454{
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100455 struct mgcp_ss7 *mgcp;
456
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800457 struct mgcp_ss7_cmd *cmd = malloc(sizeof(*cmd));
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100458 if (!cmd) {
459 LOGP(DMGCP, LOGL_ERROR, "Failed to send a command.\n");
460 return;
461 }
462
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800463 memset(cmd, 0, sizeof(*cmd));
464 cmd->type = type;
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100465 cmd->endp = endp;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800466 cmd->param = param;
467
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100468 mgcp = endp->tcfg->cfg->data;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800469 thread_safe_add(mgcp->cmd_queue, &cmd->entry);
470}
471
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100472static int ss7_allocate_endpoint(struct mgcp_ss7 *ss7, struct mgcp_endpoint *mg_endp)
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800473{
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100474 mg_endp->bts_end.rtp_port = htons(mg_endp->bts_end.local_port);
475 mg_endp->bts_end.rtcp_port = htons(mg_endp->bts_end.local_port + 1);
476 mg_endp->bts_end.addr = ss7->cfg->bts_in;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800477
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100478 mgcp_ss7_exec(mg_endp, MGCP_SS7_ALLOCATE, 0);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800479 return MGCP_POLICY_CONT;
480}
481
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100482static int ss7_modify_endpoint(struct mgcp_ss7 *ss7, struct mgcp_endpoint *mg_endp)
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800483{
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100484 mgcp_ss7_exec(mg_endp, MGCP_SS7_MUTE_STATUS, mg_endp->conn_mode);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800485
486 /*
Holger Hans Peter Freythere3abeb12010-10-18 19:36:50 +0200487 * Just assume that we have the data now.
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800488 */
Holger Hans Peter Freythere3abeb12010-10-18 19:36:50 +0200489 mgcp_send_dummy(mg_endp);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800490
491 /* update the remote end */
492 return MGCP_POLICY_CONT;
493}
494
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100495static int ss7_delete_endpoint(struct mgcp_ss7 *ss7, struct mgcp_endpoint *endp)
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800496{
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100497 mgcp_ss7_endp_free(endp);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800498 return MGCP_POLICY_CONT;
499}
500
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100501static int mgcp_ss7_policy(struct mgcp_trunk_config *tcfg, int endp_no, int state, const char *trans)
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800502{
503 int rc;
504 struct mgcp_ss7 *ss7;
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100505 struct mgcp_endpoint *endp;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800506
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100507
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100508
509 endp = &tcfg->endpoints[endp_no];
510 ss7 = (struct mgcp_ss7 *) tcfg->cfg->data;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800511
Holger Hans Peter Freyther8e6d4c32011-03-21 15:14:04 +0100512 /* these endpoints are blocked */
513 if (endp->blocked) {
514 LOGP(DMGCP, LOGL_NOTICE, "Rejecting non voice timeslots 0x%x\n", endp_no);
515 return MGCP_POLICY_REJECT;
516 }
517
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800518 /* TODO: Make it async and wait for the port to be connected */
519 rc = MGCP_POLICY_REJECT;
520 switch (state) {
521 case MGCP_ENDP_CRCX:
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100522 rc = ss7_allocate_endpoint(ss7, endp);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800523 break;
524 case MGCP_ENDP_MDCX:
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100525 rc = ss7_modify_endpoint(ss7, endp);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800526 break;
527 case MGCP_ENDP_DLCX:
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100528 rc = ss7_delete_endpoint(ss7, endp);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800529 break;
530 }
531
532 return rc;
533}
534
Harald Welteff397ed2011-05-08 10:29:23 +0200535static void enqueue_msg(struct osmo_wqueue *queue, struct sockaddr_in *addr, struct msgb *msg)
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800536{
537 struct sockaddr_in *data;
538
539 data = (struct sockaddr_in *) msgb_push(msg, sizeof(*data));
540 *data = *addr;
Harald Welteff397ed2011-05-08 10:29:23 +0200541 if (osmo_wqueue_enqueue(queue, msg) != 0) {
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800542 LOGP(DMGCP, LOGL_ERROR, "Failed to queue the message.\n");
543 msgb_free(msg);
544 }
545}
546
Harald Welteff397ed2011-05-08 10:29:23 +0200547static int write_call_agent(struct osmo_fd *bfd, struct msgb *msg)
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800548{
549 int rc;
550 struct sockaddr_in *addr;
551
552 addr = (struct sockaddr_in *) msg->data;
553 rc = sendto(bfd->fd, msg->l2h, msgb_l2len(msg), 0,
554 (struct sockaddr *) addr, sizeof(*addr));
555
556 if (rc != msgb_l2len(msg))
557 LOGP(DMGCP, LOGL_ERROR, "Failed to write MGCP message: rc: %d errno: %d\n", rc, errno);
558
559 return rc;
560}
561
562
Harald Welteff397ed2011-05-08 10:29:23 +0200563static int read_call_agent(struct osmo_fd *fd)
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800564{
565 struct sockaddr_in addr;
566 socklen_t slen = sizeof(addr);
567 struct msgb *resp;
568 struct mgcp_ss7 *cfg;
Harald Welteff397ed2011-05-08 10:29:23 +0200569 struct osmo_wqueue *queue;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800570
571 cfg = (struct mgcp_ss7 *) fd->data;
Harald Welteff397ed2011-05-08 10:29:23 +0200572 queue = container_of(fd, struct osmo_wqueue, bfd);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800573
574 /* read one less so we can use it as a \0 */
575 int rc = recvfrom(fd->fd, cfg->mgcp_msg->data, cfg->mgcp_msg->data_len - 1, 0,
576 (struct sockaddr *) &addr, &slen);
577
578 if (rc < 0) {
579 perror("Gateway failed to read");
580 return -1;
581 } else if (slen > sizeof(addr)) {
582 fprintf(stderr, "Gateway received message from outerspace: %d %d\n",
583 slen, sizeof(addr));
584 return -1;
585 }
586
587 /* handle message now */
588 cfg->mgcp_msg->l2h = msgb_put(cfg->mgcp_msg, rc);
589 resp = mgcp_handle_message(cfg->cfg, cfg->mgcp_msg);
590 msgb_reset(cfg->mgcp_msg);
591
592 if (resp)
593 enqueue_msg(queue, &addr, resp);
594 return 0;
595}
596
597static int create_socket(struct mgcp_ss7 *cfg)
598{
599 int on;
600 struct sockaddr_in addr;
Harald Welteff397ed2011-05-08 10:29:23 +0200601 struct osmo_fd *bfd;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800602
603 bfd = &cfg->mgcp_fd.bfd;
604
605 cfg->mgcp_fd.read_cb = read_call_agent;
606 cfg->mgcp_fd.write_cb = write_call_agent;
607 bfd->when = BSC_FD_READ;
608 bfd->fd = socket(AF_INET, SOCK_DGRAM, 0);
609 if (bfd->fd < 0) {
610 perror("Gateway failed to listen");
611 return -1;
612 }
613
614 on = 1;
615 setsockopt(bfd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
616
617 memset(&addr, 0, sizeof(addr));
618 addr.sin_family = AF_INET;
619 addr.sin_port = htons(cfg->cfg->source_port);
620 addr.sin_addr.s_addr = INADDR_ANY;
621
622 if (bind(bfd->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
623 perror("Gateway failed to bind");
624 close(bfd->fd);
625 return -1;
626 }
627
628 bfd->data = cfg;
629 cfg->mgcp_msg = msgb_alloc(4096, "mgcp-msg");
630 if (!cfg->mgcp_msg) {
631 fprintf(stderr, "Gateway memory error.\n");
632 close(bfd->fd);
633 return -1;
634 }
635 talloc_steal(cfg, cfg->mgcp_msg);
636
637
Harald Welteff397ed2011-05-08 10:29:23 +0200638 if (osmo_fd_register(bfd) != 0) {
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800639 DEBUGP(DMGCP, "Failed to register the fd\n");
640 close(bfd->fd);
641 return -1;
642 }
643
644 return 0;
645}
646
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100647static void mgcp_ss7_endp_free(struct mgcp_endpoint *endp)
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800648{
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100649 mgcp_ss7_exec(endp, MGCP_SS7_DELETE, 0);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800650}
651
652static int reset_cb(struct mgcp_config *cfg)
653{
654 mgcp_ss7_reset((struct mgcp_ss7 *) cfg->data);
655 return 0;
656}
657
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100658static int realloc_cb(struct mgcp_trunk_config *tcfg, int endp_no)
Holger Hans Peter Freyther95cac742010-09-18 03:16:52 +0800659{
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100660 struct mgcp_endpoint *endp = &tcfg->endpoints[endp_no];
661 mgcp_ss7_endp_free(endp);
Holger Hans Peter Freyther95cac742010-09-18 03:16:52 +0800662 return 0;
663}
664
Holger Hans Peter Freytherdea0ccc2011-09-14 01:42:22 +0200665static int configure_trunk(struct mgcp_trunk_config *tcfg, int *dsp_resource)
666{
667 int i, start;
668
669 start = tcfg->trunk_type == MGCP_TRUNK_VIRTUAL ?
670 tcfg->target_trunk_start : tcfg->trunk_nr;
671
672 for (i = 1; i < tcfg->number_endpoints; ++i) {
673 if (tcfg->endpoints[i].blocked)
674 continue;
675
676 *dsp_resource += 1;
677 tcfg->endpoints[i].hw_snmp_port = *dsp_resource;
678
679 if (tcfg->cfg->configure_trunks) {
680 int multiplex, timeslot, res;
681
682 mgcp_endpoint_to_timeslot(i, &multiplex, &timeslot);
683 res = mgcp_snmp_connect(*dsp_resource,
684 start + multiplex,
685 timeslot);
686
687 if (res != 0) {
688 LOGP(DMGCP, LOGL_ERROR,
689 "Failed to configure trunk Type: %s Trunk: %d\n",
690 tcfg->trunk_type == MGCP_TRUNK_VIRTUAL ?
691 "virtual" : "trunk", start);
692 return -1;
693 }
694 }
695 }
696
697 return 0;
698}
699
Holger Hans Peter Freytherf9e99772010-08-04 07:10:55 +0800700static struct mgcp_ss7 *mgcp_ss7_init(struct mgcp_config *cfg)
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800701{
Holger Hans Peter Freytherd3849122011-03-01 14:38:47 +0100702 struct mgcp_trunk_config *trunk;
703 int dsp_resource, i;
704
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800705 struct mgcp_ss7 *conf = talloc_zero(NULL, struct mgcp_ss7);
706 if (!conf)
707 return NULL;
708
Harald Welteff397ed2011-05-08 10:29:23 +0200709 osmo_wqueue_init(&conf->mgcp_fd, 30);
Holger Hans Peter Freytherf9e99772010-08-04 07:10:55 +0800710 conf->cfg = cfg;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800711
712 /* take over the ownership */
713 talloc_steal(conf, conf->cfg);
Holger Hans Peter Freytherf9e99772010-08-04 07:10:55 +0800714
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800715 conf->cfg->policy_cb = mgcp_ss7_policy;
716 conf->cfg->reset_cb = reset_cb;
Holger Hans Peter Freyther95cac742010-09-18 03:16:52 +0800717 conf->cfg->realloc_cb = realloc_cb;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800718 conf->cfg->data = conf;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800719
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800720 if (create_socket(conf) != 0) {
721 LOGP(DMGCP, LOGL_ERROR, "Failed to create socket.\n");
722 talloc_free(conf);
723 return NULL;
724 }
725
Holger Hans Peter Freytherb7299a82011-03-01 15:48:05 +0100726 if (cfg->configure_trunks && mgcp_snmp_init() != 0) {
727 LOGP(DMGCP, LOGL_ERROR, "Failed to initialize SNMP.\n");
728 talloc_free(conf);
729 return NULL;
730 }
731
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100732 /* Now do the init of the trunks */
Holger Hans Peter Freytherd3849122011-03-01 14:38:47 +0100733 dsp_resource = 0;
734 for (i = 1; i < cfg->trunk.number_endpoints; ++i) {
Holger Hans Peter Freytherdea0ccc2011-09-14 01:42:22 +0200735 if (configure_trunk(&cfg->trunk, &dsp_resource) != 0) {
736 talloc_free(conf);
737 return NULL;
Holger Hans Peter Freytherb7299a82011-03-01 15:48:05 +0100738 }
Holger Hans Peter Freytherd3849122011-03-01 14:38:47 +0100739 }
740
741 llist_for_each_entry(trunk, &cfg->trunks, entry) {
Holger Hans Peter Freytherdea0ccc2011-09-14 01:42:22 +0200742 if (configure_trunk(trunk, &dsp_resource) != 0) {
743 talloc_free(conf);
744 return NULL;
Holger Hans Peter Freytherd3849122011-03-01 14:38:47 +0100745 }
746 }
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800747
748 conf->cmd_queue = thread_notifier_alloc();
749 if (!conf->cmd_queue) {
750 LOGP(DMGCP, LOGL_ERROR, "Failed to allocate the command queue.\n");
751 talloc_free(conf);
752 return NULL;
753 }
754
755#ifndef NO_UNIPORTE
756 conf->cmd_queue->no_write = 1;
757 pthread_create(&conf->thread, NULL, start_uniporte, conf);
758#endif
759
760 return conf;
761}
762
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100763static void free_trunk(struct mgcp_trunk_config *trunk)
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800764{
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100765 int i;
766 for (i = 1; i < trunk->number_endpoints; ++i) {
767 struct mgcp_endpoint *endp = &trunk->endpoints[i];
768 mgcp_ss7_endp_free(endp);
769 mgcp_free_endp(endp);
770 }
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800771}
772
773void mgcp_ss7_reset(struct mgcp_ss7 *mgcp)
774{
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100775 struct mgcp_trunk_config *trunk;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800776
777 if (!mgcp)
778 return;
779
780 LOGP(DMGCP, LOGL_INFO, "Resetting all endpoints.\n");
781
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100782 /* free UniPorte and MGCP data */
783 free_trunk(&mgcp->cfg->trunk);
784
785 llist_for_each_entry(trunk, &mgcp->cfg->trunks, entry)
786 free_trunk(trunk);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800787}
788
789static void print_help()
790{
791 printf(" Some useful help...\n");
792 printf(" -h This help text.\n");
793 printf(" -c --config=CFG. The configuration file.\n");
794 printf(" -e --exit-on-failure. Exit the app on MGW failure.\n");
795}
796
797static void print_usage()
798{
799 printf("Usage: mgcp_mgw\n");
800}
801
802
803static void handle_options(int argc, char **argv)
804{
805 while (1) {
806 int option_index = 0, c;
807 static struct option long_options[] = {
808 {"help", 0, 0, 'h'},
809 {"config", 1, 0, 'c'},
810 {"exit", 0, 0, 'e'},
811 {0, 0, 0, 0},
812 };
813
814 c = getopt_long(argc, argv, "hc:e",
815 long_options, &option_index);
816 if (c == -1)
817 break;
818
819 switch (c) {
820 case 'h':
821 print_usage();
822 print_help();
823 exit(0);
824 case 'c':
825 config_file = optarg;
826 break;
827 case 'e':
828 exit_on_failure = 1;
829 break;
830 default:
831 fprintf(stderr, "Unknown option.\n");
832 break;
833 }
834 }
835}
836
837
838int main(int argc, char **argv)
839{
840 struct mgcp_ss7 *mgcp;
Holger Hans Peter Freythercc1a9382010-08-04 06:24:04 +0800841 int rc;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800842
Holger Hans Peter Freytherc21c0d62011-07-22 09:00:23 +0200843 osmo_init_logging(&log_info);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800844
845 /* enable filters */
Holger Hans Peter Freytherc21c0d62011-07-22 09:00:23 +0200846 log_set_category_filter(osmo_stderr_target, DSCCP, 1, LOGL_INFO);
847 log_set_category_filter(osmo_stderr_target, DMSC, 1, LOGL_INFO);
848 log_set_category_filter(osmo_stderr_target, DMGCP, 1, LOGL_INFO);
849 log_set_print_timestamp(osmo_stderr_target, 1);
850 log_set_use_color(osmo_stderr_target, 0);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800851
852 handle_options(argc, argv);
853
854 signal(SIGPIPE, SIG_IGN);
855
856 mgcp_mgw_vty_init();
Holger Hans Peter Freytherf41617b2010-08-04 07:08:33 +0800857
Holger Hans Peter Freyther757f1742010-09-17 22:03:08 +0800858 g_cfg = mgcp_config_alloc();
859 if (!g_cfg) {
Holger Hans Peter Freytherf41617b2010-08-04 07:08:33 +0800860 LOGP(DMGCP, LOGL_ERROR, "Failed to allocate mgcp config.\n");
861 return -1;
862 }
863
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100864 if (mgcp_parse_config(config_file, g_cfg) != 0) {
865 LOGP(DMGCP, LOGL_ERROR,
866 "Failed to parse the config file: '%s'\n", config_file);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800867 return -1;
868 }
869
Holger Hans Peter Freythercc1a9382010-08-04 06:24:04 +0800870 rc = telnet_init(NULL, NULL, 4243);
871 if (rc < 0)
872 return rc;
873
Holger Hans Peter Freytherdcc33122011-03-01 01:24:10 +0100874 printf("Creating MGCP MGW ip: %s mgw: %s\n",
875 g_cfg->local_ip, g_cfg->bts_ip);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800876
Holger Hans Peter Freyther757f1742010-09-17 22:03:08 +0800877 mgcp = mgcp_ss7_init(g_cfg);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800878 if (!mgcp) {
879 fprintf(stderr, "Failed to create MGCP\n");
880 exit(-1);
881 }
882 while (1) {
Harald Welteff397ed2011-05-08 10:29:23 +0200883 osmo_select_main(0);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800884 }
885 return 0;
886}
887