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