Display source and destination interface at endpoint logging
[lcr.git] / gsm_bs.cpp
1 /*****************************************************************************\
2 **                                                                           **
3 ** LCR                                                                       **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** mISDN gsm (BS mode)                                                       **
9 **                                                                           **
10 \*****************************************************************************/ 
11
12 #include "main.h"
13 #include "mncc.h"
14
15 struct lcr_gsm *gsm_bs = NULL;
16
17 #define PAYLOAD_TYPE_GSM 3
18
19 /*
20  * DTMF stuff
21  */
22 unsigned char dtmf_samples[16][8000];
23 static int dtmf_x[4] = { 1209, 1336, 1477, 1633 };
24 static int dtmf_y[4] = { 697, 770, 852, 941 };
25
26 void generate_dtmf(void)
27 {
28         double fx, fy, sample;
29         int i, x, y;
30         unsigned char *law;
31
32         for (y = 0; y < 4; y++) {
33                 fy = 2 * 3.1415927 * ((double)dtmf_y[y]) / 8000.0;
34                 for (x = 0; x < 4; x++) {
35                         fx = 2 * 3.1415927 * ((double)dtmf_x[x]) / 8000.0;
36                         law = dtmf_samples[y << 2 | x];
37                         for (i = 0; i < 8000; i++) {
38                                 sample = sin(fy * ((double)i)) * 0.251 * 32767.0; /* -6 dB */
39                                 sample += sin(fx * ((double)i)) * 0.158 * 32767.0; /* -8 dB */
40                                 *law++ = audio_s16_to_law[(int)sample & 0xffff];
41                         }
42                 }
43         }
44 }
45
46
47 /*
48  * constructor
49  */
50 Pgsm_bs::Pgsm_bs(int type, char *portname, struct port_settings *settings, struct interface *interface) : Pgsm(type, portname, settings, interface)
51 {
52         p_g_lcr_gsm = gsm_bs;
53         p_g_dtmf = NULL;
54         p_g_dtmf_index = 0;
55
56         PDEBUG(DEBUG_GSM, "Created new GSMBSPort(%s).\n", portname);
57 }
58
59 /*
60  * destructor
61  */
62 Pgsm_bs::~Pgsm_bs()
63 {
64         PDEBUG(DEBUG_GSM, "Destroyed GSM BS process(%s).\n", p_name);
65 }
66
67 static const char *media_type2name(unsigned char media_type) {
68         switch (media_type) {
69         case MEDIA_TYPE_ULAW:
70                 return "PCMU";
71         case MEDIA_TYPE_ALAW:
72                 return "PCMA";
73         case MEDIA_TYPE_GSM:
74                 return "GSM";
75         case MEDIA_TYPE_GSM_HR:
76                 return "GSM-HR";
77         case MEDIA_TYPE_GSM_EFR:
78                 return "GSM-EFR";
79         case MEDIA_TYPE_AMR:
80                 return "AMR";
81         }
82
83         return "UKN";
84 }
85
86 /* PROCEEDING INDICATION (from MS) */
87 void Pgsm_bs::call_conf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
88 {
89         int media_types[8];
90         unsigned char payload_types[8];
91         int payloads = 0;
92
93         gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
94         if (mncc->fields & MNCC_F_CAUSE) {
95                 add_trace("cause", "coding", "%d", mncc->cause.coding);
96                 add_trace("cause", "location", "%", mncc->cause.location);
97                 add_trace("cause", "value", "%", mncc->cause.value);
98         }
99         end_trace();
100
101         new_state(PORT_STATE_OUT_PROCEEDING);
102
103         /* get list of offered payload types
104          * if list ist empty, the FR V1 is selected */
105         select_payload_type(mncc, payload_types, media_types, &payloads, sizeof(payload_types));
106         /* if no given payload type is supported, we assume  */
107         if (!payloads) {
108                 media_types[0] = MEDIA_TYPE_GSM;
109                 payload_types[0] = PAYLOAD_TYPE_GSM;
110                 payloads = 1;
111         }
112
113         /* select first payload type that matches the rtp list */
114         if (p_g_rtp_bridge) {
115                 int i, j;
116
117                 for (i = 0; i < p_g_rtp_payloads; i++) {
118                         for (j = 0; j < payloads; j++) {
119                                 if (p_g_rtp_media_types[i] == media_types[j])
120                                         break;
121                         }
122                         if (j < payloads)
123                                 break;
124                 }
125                 if (i == p_g_rtp_payloads) {
126                         struct lcr_msg *message;
127
128                         /* payload offered by remote RTP is not supported */
129                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
130                         message->param.disconnectinfo.cause = 65;
131                         message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
132                         message_put(message);
133                         /* send release */
134                         mncc = create_mncc(MNCC_REL_REQ, p_g_callref);
135                         gsm_trace_header(p_g_interface_name, this, MNCC_REL_REQ, DIRECTION_OUT);
136                         mncc->fields |= MNCC_F_CAUSE;
137                         mncc->cause.coding = 3;
138                         mncc->cause.location = LOCATION_PRIVATE_LOCAL;
139                         mncc->cause.value = 65;
140                         add_trace("cause", "coding", "%d", mncc->cause.coding);
141                         add_trace("cause", "location", "%d", mncc->cause.location);
142                         add_trace("cause", "value", "%d", mncc->cause.value);
143                         add_trace("reason", NULL, "None of the payload types are supported by MS");
144                         end_trace();
145                         send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
146                         new_state(PORT_STATE_RELEASE);
147                         trigger_work(&p_g_delete);
148
149                         return;
150                 }
151                 modify_lchan(p_g_rtp_media_types[i]);
152                 /* use the payload type from received rtp list, not from locally generated payload types */
153                 p_g_payload_type = p_g_rtp_payload_types[i];
154         } else {
155                 /* modify to first given payload */
156                 modify_lchan(media_types[0]);
157                 p_g_payload_type = payload_types[0];
158         }
159 }
160
161 /* DTMF INDICATION */
162 void Pgsm_bs::start_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
163 {
164         struct gsm_mncc *resp;
165
166         gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
167         add_trace("keypad", NULL, "%c", mncc->keypad);
168         end_trace();
169         SPRINT(p_dialinginfo.id, "%c", mncc->keypad);
170         p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
171
172         /* send resp */
173         gsm_trace_header(p_g_interface_name, this, MNCC_START_DTMF_RSP, DIRECTION_OUT);
174         add_trace("keypad", NULL, "%c", mncc->keypad);
175         end_trace();
176         resp = create_mncc(MNCC_START_DTMF_RSP, p_g_callref);
177         resp->fields |= MNCC_F_KEYPAD;
178         resp->keypad = mncc->keypad;
179         send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
180
181         if (p_g_rtp_bridge) {
182                 /* if two members are bridged */
183                 if (p_bridge && p_bridge->first && p_bridge->first->next && !p_bridge->first->next->next) {
184                         class Port *remote = NULL;
185
186                         /* select other member */
187                         if (p_bridge->first->port == this)
188                                 remote = p_bridge->first->next->port;
189                         if (p_bridge->first->next->port == this)
190                                 remote = p_bridge->first->port;
191
192                         if (remote) {
193                                 struct lcr_msg *message;
194
195                                 /* send dtmf information, because we bridge RTP directly */
196                                 message = message_create(0, remote->p_serial, EPOINT_TO_PORT, MESSAGE_DTMF);
197                                 message->param.dtmf = mncc->keypad;
198                                 message_put(message);
199                         }
200                 }
201         } else {
202                 /* generate DTMF tones, since we do audio forwarding inside LCR */
203                 switch (mncc->keypad) {
204                         case '1': p_g_dtmf = dtmf_samples[0]; break;
205                         case '2': p_g_dtmf = dtmf_samples[1]; break;
206                         case '3': p_g_dtmf = dtmf_samples[2]; break;
207                         case 'a':
208                         case 'A': p_g_dtmf = dtmf_samples[3]; break;
209                         case '4': p_g_dtmf = dtmf_samples[4]; break;
210                         case '5': p_g_dtmf = dtmf_samples[5]; break;
211                         case '6': p_g_dtmf = dtmf_samples[6]; break;
212                         case 'b':
213                         case 'B': p_g_dtmf = dtmf_samples[7]; break;
214                         case '7': p_g_dtmf = dtmf_samples[8]; break;
215                         case '8': p_g_dtmf = dtmf_samples[9]; break;
216                         case '9': p_g_dtmf = dtmf_samples[10]; break;
217                         case 'c':
218                         case 'C': p_g_dtmf = dtmf_samples[11]; break;
219                         case '*': p_g_dtmf = dtmf_samples[12]; break;
220                         case '0': p_g_dtmf = dtmf_samples[13]; break;
221                         case '#': p_g_dtmf = dtmf_samples[14]; break;
222                         case 'd':
223                         case 'D': p_g_dtmf = dtmf_samples[15]; break;
224                 }
225                 p_g_dtmf_index = 0;
226         }
227 }
228 void Pgsm_bs::stop_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
229 {
230         struct gsm_mncc *resp;
231
232         gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
233         add_trace("keypad", NULL, "%c", mncc->keypad);
234         end_trace();
235
236         /* send resp */
237         gsm_trace_header(p_g_interface_name, this, MNCC_STOP_DTMF_RSP, DIRECTION_OUT);
238         add_trace("keypad", NULL, "%c", mncc->keypad);
239         end_trace();
240         resp = create_mncc(MNCC_STOP_DTMF_RSP, p_g_callref);
241         resp->keypad = mncc->keypad;
242         send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
243         
244         /* stop DTMF */
245         p_g_dtmf = NULL;
246 }
247
248 /* HOLD INDICATION */
249 void Pgsm_bs::hold_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
250 {
251         struct lcr_msg *message;
252         struct gsm_mncc *resp, *frame;
253
254         gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
255         end_trace();
256
257         /* notify the hold of call */
258         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
259         message->param.notifyinfo.notify = INFO_NOTIFY_REMOTE_HOLD;
260         message->param.notifyinfo.local = 1; /* call is held by supplementary service */
261         message_put(message);
262
263         /* acknowledge hold */
264         gsm_trace_header(p_g_interface_name, this, MNCC_HOLD_CNF, DIRECTION_OUT);
265         end_trace();
266         resp = create_mncc(MNCC_HOLD_CNF, p_g_callref);
267         send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
268
269         /* disable audio */
270         if (p_g_tch_connected) { /* it should be true */
271                 gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_DROP, DIRECTION_OUT);
272                 end_trace();
273                 frame = create_mncc(MNCC_FRAME_DROP, p_g_callref);
274                 send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
275                 p_g_tch_connected = 0;
276         }
277 }
278
279
280 /* RETRIEVE INDICATION */
281 void Pgsm_bs::retr_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
282 {
283         struct lcr_msg *message;
284         struct gsm_mncc *resp, *frame;
285
286         gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
287         end_trace();
288
289         /* notify the retrieve of call */
290         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
291         message->param.notifyinfo.notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
292         message->param.notifyinfo.local = 1; /* call is retrieved by supplementary service */
293         message_put(message);
294
295         /* acknowledge retr */
296         gsm_trace_header(p_g_interface_name, this, MNCC_RETRIEVE_CNF, DIRECTION_OUT);
297         end_trace();
298         resp = create_mncc(MNCC_RETRIEVE_CNF, p_g_callref);
299         send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
300
301         /* enable audio */
302         if (!p_g_tch_connected) { /* it should be true */
303                 gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
304                 end_trace();
305                 frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
306                 send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
307                 p_g_tch_connected = 1;
308         }
309 }
310
311 /*
312  * select payload type by given list or GSM V1 FR 
313  * return the payload type or 0 if not given 
314  */
315
316 void Pgsm_bs::select_payload_type(struct gsm_mncc *mncc, unsigned char *payload_types, int *media_types, int *payloads, int max_payloads)
317 {
318         int media_type;
319         unsigned char payload_type;
320
321         *payloads = 0;
322
323         gsm_trace_header(p_g_interface_name, this, 1 /* codec negotioation */, DIRECTION_NONE);
324         if ((mncc->fields & MNCC_F_BEARER_CAP)) {
325                 /* select preferred payload type from list */
326                 int i;
327                 unsigned char dynamic_type = 96;
328
329                 add_trace("bearer", "capa", "given by MS");
330                 for (i = 0; mncc->bearer_cap.speech_ver[i] >= 0; i++) {
331                         /* select payload type we support */
332                         switch (mncc->bearer_cap.speech_ver[i]) {
333                         case 0:
334                                 add_trace("speech", "version", "Full Rate given");
335                                 media_type = MEDIA_TYPE_GSM;
336                                 payload_type = PAYLOAD_TYPE_GSM;
337                                 break;
338                         case 2:
339                                 add_trace("speech", "version", "EFR given");
340                                 media_type = MEDIA_TYPE_GSM_EFR;
341                                 payload_type = dynamic_type++;
342                                 break;
343                         case 4:
344                                 add_trace("speech", "version", "AMR given");
345                                 media_type = MEDIA_TYPE_AMR;
346                                 payload_type = dynamic_type++;
347                                 break;
348                         case 1:
349                                 add_trace("speech", "version", "Half Rate given");
350                                 media_type = MEDIA_TYPE_GSM_HR;
351                                 payload_type = dynamic_type++;
352                                 break;
353                         case 5:
354                                 add_trace("speech", "version", "AMR Half Rate given");
355                                 media_type = MEDIA_TYPE_AMR;
356                                 payload_type = dynamic_type++;
357                                 break;
358                         default:
359                                 add_trace("speech", "version", "%d given", mncc->bearer_cap.speech_ver[i]);
360                                 media_type = 0;
361                                 payload_type = 0;
362                         }
363                         /* wen don't support it, so we check the next */
364                         if (!media_type) {
365                                 add_trace("speech", "ignored", "Not supported by LCR");
366                                 continue;
367                         }
368                         if (!p_g_rtp_bridge) {
369                                 if (media_type != MEDIA_TYPE_GSM) {
370                                         add_trace("speech", "ignored", "Not suitable for LCR");
371                                         continue;
372                                 }
373                         }
374                         if (*payloads <= max_payloads) {
375                                 media_types[*payloads] = media_type;
376                                 payload_types[*payloads] = payload_type;
377                                 (*payloads)++;
378                         }
379                 }
380         } else {
381                 add_trace("bearer", "capa", "not given by MS");
382                 add_trace("speech", "version", "Full Rate given");
383                 media_types[0] = MEDIA_TYPE_GSM;
384                 payload_types[0] = PAYLOAD_TYPE_GSM;
385                 *payloads = 1;
386         }
387         if (!(*payloads))
388                 add_trace("error", "", "All given payload types unsupported");
389         end_trace();
390 }
391
392 /*
393  * handles all indications
394  */
395 /* SETUP INDICATION */
396 void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
397 {
398         class Endpoint *epoint;
399         struct lcr_msg *message;
400         struct gsm_mncc *proceeding, *frame;
401         struct interface *interface;
402         int media_types[8];
403         unsigned char payload_types[8];
404         int payloads = 0;
405
406         interface = getinterfacebyname(p_g_interface_name);
407         if (!interface) {
408                 PERROR("Cannot find interface %s.\n", p_g_interface_name);
409                 return;
410         }
411
412         /* process given callref */
413         gsm_trace_header(p_g_interface_name, this, 0, DIRECTION_IN);
414         add_trace("callref", "new", "0x%x", callref);
415         if (p_g_callref) {
416                 /* release in case the ID is already in use */
417                 add_trace("error", NULL, "callref already in use");
418                 end_trace();
419                 mncc = create_mncc(MNCC_REJ_REQ, callref);
420                 gsm_trace_header(p_g_interface_name, this, MNCC_REJ_REQ, DIRECTION_OUT);
421                 mncc->fields |= MNCC_F_CAUSE;
422                 mncc->cause.coding = 3;
423                 mncc->cause.location = 1;
424                 mncc->cause.value = 47;
425                 add_trace("cause", "coding", "%d", mncc->cause.coding);
426                 add_trace("cause", "location", "%d", mncc->cause.location);
427                 add_trace("cause", "value", "%d", mncc->cause.value);
428                 add_trace("reason", NULL, "callref already in use");
429                 end_trace();
430                 send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
431                 new_state(PORT_STATE_RELEASE);
432                 trigger_work(&p_g_delete);
433                 return;
434         }
435         p_g_callref = callref;
436         end_trace();
437
438         /* caller info */
439         if (mncc->clir.inv)
440                 p_callerinfo.present = INFO_PRESENT_RESTRICTED;
441         else
442                 p_callerinfo.present = INFO_PRESENT_ALLOWED;
443         if (mncc->calling.number[0])
444                 SCPY(p_callerinfo.id, mncc->calling.number);
445         else
446                 p_callerinfo.present = INFO_PRESENT_NOTAVAIL;
447         SCPY(p_callerinfo.imsi, mncc->imsi);
448         p_callerinfo.screen = INFO_SCREEN_NETWORK;
449         p_callerinfo.ntype = INFO_NTYPE_UNKNOWN;
450         SCPY(p_callerinfo.interface, p_g_interface_name);
451
452         /* dialing information */
453         SCAT(p_dialinginfo.id, mncc->called.number);
454         switch (mncc->called.type) {
455                 case 0x1:
456                 p_dialinginfo.ntype = INFO_NTYPE_INTERNATIONAL;
457                 break;
458                 case 0x2:
459                 p_dialinginfo.ntype = INFO_NTYPE_NATIONAL;
460                 break;
461                 case 0x4:
462                 p_dialinginfo.ntype = INFO_NTYPE_SUBSCRIBER;
463                 break;
464                 default:
465                 p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
466                 break;
467         }
468         if (mncc->emergency) {
469                 SCPY(p_dialinginfo.id, "emergency");
470         }
471         p_dialinginfo.sending_complete = 1;
472
473         /* bearer capability */
474         p_capainfo.bearer_capa = INFO_BC_SPEECH;
475         p_capainfo.bearer_info1 = (options.law=='a')?3:2;
476         p_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
477         p_capainfo.source_mode = B_MODE_TRANSPARENT;
478         p_g_mode = p_capainfo.source_mode;
479
480         /* get list of offered payload types
481          * if list ist empty, the FR V1 is selected */
482         select_payload_type(mncc, payload_types, media_types, &payloads, sizeof(payload_types));
483         /* if no given payload type is supported, we assume  */
484         if (!payloads) {
485                 media_types[0] = MEDIA_TYPE_GSM;
486                 payload_types[0] = PAYLOAD_TYPE_GSM;
487                 payloads = 1;
488         }
489 #if 0
490         /* if no given payload type is supported, we reject the call */
491         if (!payloads) {
492                 mncc = create_mncc(MNCC_REJ_REQ, callref);
493                 gsm_trace_header(p_g_interface_name, this, MNCC_REJ_REQ, DIRECTION_OUT);
494                 mncc->fields |= MNCC_F_CAUSE;
495                 mncc->cause.coding = 3;
496                 mncc->cause.location = 1;
497                 mncc->cause.value = 65;
498                 add_trace("cause", "coding", "%d", mncc->cause.coding);
499                 add_trace("cause", "location", "%d", mncc->cause.location);
500                 add_trace("cause", "value", "%d", mncc->cause.value);
501                 add_trace("reason", NULL, "Given speech codec(s) not supported");
502                 end_trace();
503                 send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
504                 new_state(PORT_STATE_RELEASE);
505                 trigger_work(&p_g_delete);
506                 return;
507         }
508 #endif
509
510         /* useruser */
511
512         /* what infos did we got ... */
513         gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
514         if (p_callerinfo.id[0])
515                 add_trace("calling", "number", "%s", p_callerinfo.id);
516         else
517                 SPRINT(p_callerinfo.id, "imsi-%s", p_callerinfo.imsi);
518         add_trace("calling", "imsi", "%s", p_callerinfo.imsi);
519         add_trace("dialing", "number", "%s", p_dialinginfo.id);
520         end_trace();
521
522         /* create endpoint */
523         if (p_epointlist)
524                 FATAL("Incoming call but already got an endpoint.\n");
525         if (!(epoint = new Endpoint(p_serial, 0)))
526                 FATAL("No memory for Endpoint instance\n");
527         epoint->ep_app = new_endpointapp(epoint, 0, interface->app); //incoming
528         epointlist_new(epoint->ep_serial);
529
530         /* modify lchan in case of no rtp bridge */
531         if (!p_g_rtp_bridge)
532                 modify_lchan(media_types[0]);
533
534         /* send call proceeding */
535         gsm_trace_header(p_g_interface_name, this, MNCC_CALL_PROC_REQ, DIRECTION_OUT);
536         proceeding = create_mncc(MNCC_CALL_PROC_REQ, p_g_callref);
537         if (p_g_tones) {
538                 proceeding->fields |= MNCC_F_PROGRESS;
539                 proceeding->progress.coding = 3; /* GSM */
540                 proceeding->progress.location = 1;
541                 proceeding->progress.descr = 8;
542                 add_trace("progress", "coding", "%d", proceeding->progress.coding);
543                 add_trace("progress", "location", "%d", proceeding->progress.location);
544                 add_trace("progress", "descr", "%d", proceeding->progress.descr);
545         }
546         end_trace();
547         send_and_free_mncc(p_g_lcr_gsm, proceeding->msg_type, proceeding);
548
549         new_state(PORT_STATE_IN_PROCEEDING);
550
551         if (p_g_tones && !p_g_tch_connected) { /* only if ... */
552                 gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
553                 end_trace();
554                 frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
555                 send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
556                 p_g_tch_connected = 1;
557         }
558
559         /* send setup message to endpoit */
560         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_SETUP);
561         message->param.setup.port_type = p_type;
562 //      message->param.setup.dtmf = 0;
563         memcpy(&message->param.setup.dialinginfo, &p_dialinginfo, sizeof(struct dialing_info));
564         memcpy(&message->param.setup.callerinfo, &p_callerinfo, sizeof(struct caller_info));
565         memcpy(&message->param.setup.capainfo, &p_capainfo, sizeof(struct capa_info));
566         SCPY((char *)message->param.setup.useruser.data, (char *)mncc->useruser.info);
567         message->param.setup.useruser.len = strlen(mncc->useruser.info);
568         message->param.setup.useruser.protocol = mncc->useruser.proto;
569         if (p_g_rtp_bridge) {
570                 struct gsm_mncc_rtp *rtp;
571                 int i;
572
573                 PDEBUG(DEBUG_GSM, "Request RTP peer info, before forwarding setup\n");
574                 p_g_setup_pending = message;
575                 rtp = (struct gsm_mncc_rtp *) create_mncc(MNCC_RTP_CREATE, p_g_callref);
576                 send_and_free_mncc(p_g_lcr_gsm, rtp->msg_type, rtp);
577
578                 for (i = 0; i < (int)sizeof(message->param.setup.rtpinfo.payload_types) && i < payloads; i++) {
579                         message->param.setup.rtpinfo.media_types[i] = media_types[i];
580                         message->param.setup.rtpinfo.payload_types[i] = payload_types[i];
581                         message->param.setup.rtpinfo.payloads++;
582                 }
583
584         } else
585                 message_put(message);
586
587 }
588
589 /*
590  * BSC sends message to port
591  */
592 int message_bsc(struct lcr_gsm *lcr_gsm, int msg_type, void *arg)
593 {
594         struct gsm_mncc *mncc = (struct gsm_mncc *)arg;
595         unsigned int callref = mncc->callref;
596         class Port *port;
597         class Pgsm_bs *pgsm_bs = NULL;
598         char name[64];
599 //      struct mISDNport *mISDNport;
600
601         /* Special messages */
602         switch(msg_type) {
603         }
604
605         /* find callref */
606         callref = mncc->callref;
607         port = port_first;
608         while(port) {
609                 if ((port->p_type & PORT_CLASS_GSM_MASK) == PORT_CLASS_GSM_BS) {
610                         pgsm_bs = (class Pgsm_bs *)port;
611                         if (pgsm_bs->p_g_callref == callref) {
612                                 break;
613                         }
614                 }
615                 port = port->next;
616         }
617
618         if (msg_type == GSM_TCHF_FRAME
619          || msg_type == GSM_BAD_FRAME) {
620                 if (port) {
621                         /* inject DTMF, if enabled */
622                         if (pgsm_bs->p_g_dtmf) {
623                                 unsigned char data[160];
624                                 int i;
625
626                                 for (i = 0; i < 160; i++) {
627                                         data[i] = pgsm_bs->p_g_dtmf[pgsm_bs->p_g_dtmf_index++];
628                                         if (pgsm_bs->p_g_dtmf_index == 8000)
629                                                 pgsm_bs->p_g_dtmf_index = 0;
630                                 }
631                                 /* send */
632                                 pgsm_bs->bridge_tx(data, 160);
633                         } else
634                                 pgsm_bs->frame_receive(arg);
635                         /* if we do not bridge we need to inject audio, if available */
636                         if (!pgsm_bs->p_bridge || pgsm_bs->p_tone_name[0]) {
637                                 unsigned char data[160];
638                                 int i;
639
640                                 i = pgsm_bs->read_audio(data, 160);
641                                 if (i)
642                                         pgsm_bs->audio_send(data, i);
643                         }
644                 }
645                 return 0;
646         }
647
648         if (!port) {
649                 struct interface *interface;
650
651                 if (msg_type != MNCC_SETUP_IND)
652                         return(0);
653
654                 interface = getinterfacebyname(lcr_gsm->interface_name);
655                 if (!interface) {
656                         struct gsm_mncc *rej;
657
658                         rej = create_mncc(MNCC_REJ_REQ, callref);
659                         rej->fields |= MNCC_F_CAUSE;
660                         rej->cause.coding = 3;
661                         rej->cause.location = 1;
662                         rej->cause.value = 27;
663                         gsm_trace_header(NULL, NULL, MNCC_REJ_REQ, DIRECTION_OUT);
664                         add_trace("cause", "coding", "%d", rej->cause.coding);
665                         add_trace("cause", "location", "%d", rej->cause.location);
666                         add_trace("cause", "value", "%d", rej->cause.value);
667                         add_trace("reason", NULL, "interface %s not found", lcr_gsm->interface_name);
668                         end_trace();
669                         send_and_free_mncc(lcr_gsm, rej->msg_type, rej);
670                         return 0;
671                 }
672                 /* creating port object, transparent until setup with hdlc */
673                 SPRINT(name, "%s-%d-in", interface->name, 0);
674                 if (!(pgsm_bs = new Pgsm_bs(PORT_TYPE_GSM_BS_IN, name, NULL, interface)))
675                         FATAL("Cannot create Port instance.\n");
676         }
677
678         switch(msg_type) {
679                 case MNCC_SETUP_IND:
680                 pgsm_bs->setup_ind(msg_type, callref, mncc);
681                 break;
682
683                 case MNCC_RTP_CREATE:
684                 pgsm_bs->rtp_create_ind(msg_type, callref, mncc);
685                 break;
686
687                 case MNCC_RTP_CONNECT:
688                 pgsm_bs->rtp_connect_ind(msg_type, callref, mncc);
689                 break;
690
691                 case MNCC_START_DTMF_IND:
692                 pgsm_bs->start_dtmf_ind(msg_type, callref, mncc);
693                 break;
694
695                 case MNCC_STOP_DTMF_IND:
696                 pgsm_bs->stop_dtmf_ind(msg_type, callref, mncc);
697                 break;
698
699                 case MNCC_CALL_CONF_IND:
700                 pgsm_bs->call_conf_ind(msg_type, callref, mncc);
701                 break;
702
703                 case MNCC_ALERT_IND:
704                 pgsm_bs->alert_ind(msg_type, callref, mncc);
705                 break;
706
707                 case MNCC_SETUP_CNF:
708                 pgsm_bs->setup_cnf(msg_type, callref, mncc);
709                 break;
710
711                 case MNCC_SETUP_COMPL_IND:
712                 pgsm_bs->setup_compl_ind(msg_type, callref, mncc);
713                 break;
714
715                 case MNCC_DISC_IND:
716                 pgsm_bs->disc_ind(msg_type, callref, mncc);
717                 break;
718
719                 case MNCC_REL_IND:
720                 case MNCC_REL_CNF:
721                 case MNCC_REJ_IND:
722                 pgsm_bs->rel_ind(msg_type, callref, mncc);
723                 break;
724
725                 case MNCC_NOTIFY_IND:
726                 pgsm_bs->notify_ind(msg_type, callref, mncc);
727                 break;
728
729                 case MNCC_HOLD_IND:
730                 pgsm_bs->hold_ind(msg_type, callref, mncc);
731                 break;
732
733                 case MNCC_RETRIEVE_IND:
734                 pgsm_bs->retr_ind(msg_type, callref, mncc);
735                 break;
736
737                 default:
738                 PDEBUG(DEBUG_GSM, "Pgsm_bs(%s) gsm port with (caller id %s) received unhandled nessage: 0x%x\n", pgsm_bs->p_name, pgsm_bs->p_callerinfo.id, msg_type);
739         }
740         return(0);
741 }
742
743 /* MESSAGE_SETUP */
744 void Pgsm_bs::message_setup(unsigned int epoint_id, int message_id, union parameter *param)
745 {
746         struct lcr_msg *message;
747         struct epoint_list *epointlist;
748         struct gsm_mncc *mncc;
749
750         /* copy setup infos to port */
751         memcpy(&p_callerinfo, &param->setup.callerinfo, sizeof(p_callerinfo));
752         memcpy(&p_dialinginfo, &param->setup.dialinginfo, sizeof(p_dialinginfo));
753         memcpy(&p_capainfo, &param->setup.capainfo, sizeof(p_capainfo));
754         memcpy(&p_redirinfo, &param->setup.redirinfo, sizeof(p_redirinfo));
755
756         /* no GSM MNCC connection */
757         if (p_g_lcr_gsm->mncc_lfd.fd < 0) {
758                 gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_REQ, DIRECTION_OUT);
759                 add_trace("failure", NULL, "No MNCC connection.");
760                 end_trace();
761                 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
762                 message->param.disconnectinfo.cause = 41; // temp. failure.
763                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
764                 message_put(message);
765                 new_state(PORT_STATE_RELEASE);
766                 trigger_work(&p_g_delete);
767                 return;
768         }
769
770         /* no number */
771         if (!p_dialinginfo.id[0]) {
772                 gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_REQ, DIRECTION_OUT);
773                 add_trace("failure", NULL, "No dialed subscriber given.");
774                 end_trace();
775                 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
776                 message->param.disconnectinfo.cause = 28;
777                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
778                 message_put(message);
779                 new_state(PORT_STATE_RELEASE);
780                 trigger_work(&p_g_delete);
781                 return;
782         }
783
784         /* unsupported codec for RTP bridge */
785         if (param->setup.rtpinfo.port) {
786                 int i;
787
788                 p_g_rtp_payloads = 0;
789                 gsm_trace_header(p_g_interface_name, this, 1 /* codec negotioation */, DIRECTION_NONE);
790                 for (i = 0; i < param->setup.rtpinfo.payloads; i++) {
791                         switch (param->setup.rtpinfo.media_types[i]) {
792                         case MEDIA_TYPE_GSM:
793                         case MEDIA_TYPE_GSM_EFR:
794                         case MEDIA_TYPE_AMR:
795                         case MEDIA_TYPE_GSM_HR:
796                                 add_trace("rtp", "payload", "%s:%d supported", media_type2name(param->setup.rtpinfo.media_types[i]), param->setup.rtpinfo.payload_types[i]);
797                                 if (p_g_rtp_payloads < (int)sizeof(p_g_rtp_payload_types)) {
798                                         p_g_rtp_media_types[p_g_rtp_payloads] = param->setup.rtpinfo.media_types[i];
799                                         p_g_rtp_payload_types[p_g_rtp_payloads] = param->setup.rtpinfo.payload_types[i];
800                                         p_g_rtp_payloads++;
801                                 }
802                                 break;
803                         default:
804                                 add_trace("rtp", "payload", "%s:%d unsupported", media_type2name(param->setup.rtpinfo.media_types[i]), param->setup.rtpinfo.payload_types[i]);
805                         }
806                 }
807                 end_trace();
808                 if (!p_g_rtp_payloads) {
809                         gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_REQ, DIRECTION_OUT);
810                         add_trace("failure", NULL, "No payload given that is supported by GSM");
811                         end_trace();
812                         message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
813                         message->param.disconnectinfo.cause = 65;
814                         message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
815                         message_put(message);
816                         new_state(PORT_STATE_RELEASE);
817                         trigger_work(&p_g_delete);
818                         return;
819                 }
820         }
821
822 //              SCPY(&p_m_tones_dir, param->setup.ext.tones_dir);
823         /* screen outgoing caller id */
824         do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_g_interface_name);
825
826         /* attach only if not already */
827         epointlist = p_epointlist;
828         while(epointlist) {
829                 if (epointlist->epoint_id == epoint_id)
830                         break;
831                 epointlist = epointlist->next;
832         }
833         if (!epointlist)
834                 epointlist_new(epoint_id);
835
836         /* creating l3id */
837         gsm_trace_header(p_g_interface_name, this, 0, DIRECTION_OUT);
838         p_g_callref = new_callref++;
839         add_trace("callref", "new", "0x%x", p_g_callref);
840         end_trace();
841
842         gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_REQ, DIRECTION_OUT);
843         mncc = create_mncc(MNCC_SETUP_REQ, p_g_callref);
844         /* caller information */
845         mncc->fields |= MNCC_F_CALLING;
846         mncc->calling.plan = 1;
847         switch (p_callerinfo.ntype) {
848                 case INFO_NTYPE_UNKNOWN:
849                 mncc->calling.type = 0x0;
850                 break;
851                 case INFO_NTYPE_INTERNATIONAL:
852                 mncc->calling.type = 0x1;
853                 break;
854                 case INFO_NTYPE_NATIONAL:
855                 mncc->calling.type = 0x2;
856                 break;
857                 case INFO_NTYPE_SUBSCRIBER:
858                 mncc->calling.type = 0x4;
859                 break;
860                 default: /* INFO_NTYPE_NOTPRESENT */
861                 mncc->fields &= ~MNCC_F_CALLING;
862                 break;
863         }
864         switch (p_callerinfo.screen) {
865                 case INFO_SCREEN_USER:
866                 mncc->calling.screen = 0;
867                 break;
868                 default: /* INFO_SCREEN_NETWORK */
869                 mncc->calling.screen = 3;
870                 break;
871         }
872         switch (p_callerinfo.present) {
873                 case INFO_PRESENT_ALLOWED:
874                 mncc->calling.present = 0;
875                 break;
876                 case INFO_PRESENT_RESTRICTED:
877                 mncc->calling.present = 1;
878                 break;
879                 default: /* INFO_PRESENT_NOTAVAIL */
880                 mncc->calling.present = 2;
881                 break;
882         }
883         if (mncc->fields & MNCC_F_CALLING) {
884                 SCPY(mncc->calling.number, p_callerinfo.id);
885                 add_trace("calling", "type", "%d", mncc->calling.type);
886                 add_trace("calling", "plan", "%d", mncc->calling.plan);
887                 add_trace("calling", "present", "%d", mncc->calling.present);
888                 add_trace("calling", "screen", "%d", mncc->calling.screen);
889                 add_trace("calling", "number", "%s", mncc->calling.number);
890         }
891         /* dialing information */
892         mncc->fields |= MNCC_F_CALLED;
893         if (!strncmp(p_dialinginfo.id, "imsi-", 5)) {
894                 SCPY(mncc->imsi, p_dialinginfo.id+5);
895                 add_trace("dialing", "imsi", "%s", mncc->imsi);
896         } else {
897                 SCPY(mncc->called.number, p_dialinginfo.id);
898                 add_trace("dialing", "number", "%s", mncc->called.number);
899         }
900         
901         /* sending user-user */
902
903         /* redirecting number */
904         mncc->fields |= MNCC_F_REDIRECTING;
905         mncc->redirecting.plan = 1;
906         switch (p_redirinfo.ntype) {
907                 case INFO_NTYPE_UNKNOWN:
908                 mncc->redirecting.type = 0x0;
909                 break;
910                 case INFO_NTYPE_INTERNATIONAL:
911                 mncc->redirecting.type = 0x1;
912                 break;
913                 case INFO_NTYPE_NATIONAL:
914                 mncc->redirecting.type = 0x2;
915                 break;
916                 case INFO_NTYPE_SUBSCRIBER:
917                 mncc->redirecting.type = 0x4;
918                 break;
919                 default: /* INFO_NTYPE_NOTPRESENT */
920                 mncc->fields &= ~MNCC_F_REDIRECTING;
921                 break;
922         }
923         switch (p_redirinfo.screen) {
924                 case INFO_SCREEN_USER:
925                 mncc->redirecting.screen = 0;
926                 break;
927                 default: /* INFO_SCREE_NETWORK */
928                 mncc->redirecting.screen = 3;
929                 break;
930         }
931         switch (p_redirinfo.present) {
932                 case INFO_PRESENT_ALLOWED:
933                 mncc->redirecting.present = 0;
934                 break;
935                 case INFO_PRESENT_RESTRICTED:
936                 mncc->redirecting.present = 1;
937                 break;
938                 default: /* INFO_PRESENT_NOTAVAIL */
939                 mncc->redirecting.present = 2;
940                 break;
941         }
942         /* sending redirecting number only in ntmode */
943         if (mncc->fields & MNCC_F_REDIRECTING) {
944                 SCPY(mncc->redirecting.number, p_redirinfo.id);
945                 add_trace("redir", "type", "%d", mncc->redirecting.type);
946                 add_trace("redir", "plan", "%d", mncc->redirecting.plan);
947                 add_trace("redir", "present", "%d", mncc->redirecting.present);
948                 add_trace("redir", "screen", "%d", mncc->redirecting.screen);
949                 add_trace("redir", "number", "%s", mncc->redirecting.number);
950         }
951
952         end_trace();
953         send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
954
955         new_state(PORT_STATE_OUT_SETUP);
956
957         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_PROCEEDING);
958         message_put(message);
959
960         /* RTP bridge */
961         if (param->setup.rtpinfo.port) {
962                 p_g_rtp_bridge = 1;
963                 p_g_rtp_ip_remote = param->setup.rtpinfo.ip;
964                 p_g_rtp_port_remote = param->setup.rtpinfo.port;
965         } else
966                 p_g_rtp_bridge = 0;
967 }
968
969 /*
970  * endpoint sends messages to the port
971  */
972 int Pgsm_bs::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
973 {
974         if (Pgsm::message_epoint(epoint_id, message_id, param))
975                 return(1);
976
977         switch(message_id) {
978                 case MESSAGE_SETUP: /* dial-out command received from epoint */
979                 if (p_state!=PORT_STATE_IDLE)
980                         break;
981                 message_setup(epoint_id, message_id, param);
982                 break;
983
984                 default:
985                 PDEBUG(DEBUG_GSM, "Pgsm_bs(%s) gsm port with (caller id %s) received unhandled nessage: %d\n", p_name, p_callerinfo.id, message_id);
986         }
987
988         return(1);
989 }
990
991 int gsm_bs_exit(int rc)
992 {
993         /* free gsm instance */
994         if (gsm_bs) {
995                 if (gsm_bs->mncc_lfd.fd > -1) {
996                         close(gsm_bs->mncc_lfd.fd);
997                         unregister_fd(&gsm_bs->mncc_lfd);
998                 }
999
1000                 del_timer(&gsm_bs->socket_retry);
1001                 free(gsm_bs);
1002                 gsm_bs = NULL;
1003         }
1004
1005
1006         return(rc);
1007 }
1008
1009 int gsm_bs_init(struct interface *interface)
1010 {
1011         /* create gsm instance */
1012         gsm_bs = (struct lcr_gsm *)MALLOC(sizeof(struct lcr_gsm));
1013
1014         SCPY(gsm_bs->interface_name, interface->name);
1015         gsm_bs->type = LCR_GSM_TYPE_NETWORK;
1016         gsm_bs->sun.sun_family = AF_UNIX;
1017         SCPY(gsm_bs->sun.sun_path, "/tmp/bsc_mncc");
1018
1019         memset(&gsm_bs->socket_retry, 0, sizeof(gsm_bs->socket_retry));
1020         add_timer(&gsm_bs->socket_retry, mncc_socket_retry_cb, gsm_bs, 0);
1021
1022         /* do the initial connect */
1023         mncc_socket_retry_cb(&gsm_bs->socket_retry, gsm_bs, 0);
1024
1025         generate_dtmf();
1026
1027         return 0;
1028 }