Disabled NUTAG_AUTO100, Entering PROCEEDING state after sending INVITE
[lcr.git] / gsm.cpp
1 /*****************************************************************************\
2 **                                                                           **
3 ** LCR                                                                       **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **            MNCC-Interface: Harald Welte                                   **
8 **                                                                           **
9 ** mISDN gsm                                                                 **
10 **                                                                           **
11 \*****************************************************************************/ 
12
13 #include "main.h"
14 #include "mncc.h"
15
16 #ifndef _GNU_SOURCE
17 #define _GNU_SOURCE
18 #endif
19 extern "C" {
20 #include "gsm_audio.h"
21 }
22
23 #include <mISDN/mISDNcompat.h>
24 #include <assert.h>
25
26 #define SOCKET_RETRY_TIMER      5
27
28 //struct lcr_gsm *gsm = NULL;
29
30 int new_callref = 1;
31
32 /* names of MNCC-SAP */
33 static const struct _value_string {
34         int msg_type;
35         const char *name;
36 } mncc_names[] = {
37         { 0,                    "New call ref" },
38         { MNCC_SETUP_REQ,       "MNCC_SETUP_REQ" },
39         { MNCC_SETUP_IND,       "MNCC_SETUP_IND" },
40         { MNCC_SETUP_RSP,       "MNCC_SETUP_RSP" },
41         { MNCC_SETUP_CNF,       "MNCC_SETUP_CNF" },
42         { MNCC_SETUP_COMPL_REQ, "MNCC_SETUP_COMPL_REQ" },
43         { MNCC_SETUP_COMPL_IND, "MNCC_SETUP_COMPL_IND" },
44         { MNCC_CALL_CONF_IND,   "MNCC_CALL_CONF_IND" },
45         { MNCC_CALL_PROC_REQ,   "MNCC_CALL_PROC_REQ" },
46         { MNCC_PROGRESS_REQ,    "MNCC_PROGRESS_REQ" },
47         { MNCC_ALERT_REQ,       "MNCC_ALERT_REQ" },
48         { MNCC_ALERT_IND,       "MNCC_ALERT_IND" },
49         { MNCC_NOTIFY_REQ,      "MNCC_NOTIFY_REQ" },
50         { MNCC_NOTIFY_IND,      "MNCC_NOTIFY_IND" },
51         { MNCC_DISC_REQ,        "MNCC_DISC_REQ" },
52         { MNCC_DISC_IND,        "MNCC_DISC_IND" },
53         { MNCC_REL_REQ,         "MNCC_REL_REQ" },
54         { MNCC_REL_IND,         "MNCC_REL_IND" },
55         { MNCC_REL_CNF,         "MNCC_REL_CNF" },
56         { MNCC_FACILITY_REQ,    "MNCC_FACILITY_REQ" },
57         { MNCC_FACILITY_IND,    "MNCC_FACILITY_IND" },
58         { MNCC_START_DTMF_IND,  "MNCC_START_DTMF_IND" },
59         { MNCC_START_DTMF_RSP,  "MNCC_START_DTMF_RSP" },
60         { MNCC_START_DTMF_REJ,  "MNCC_START_DTMF_REJ" },
61         { MNCC_STOP_DTMF_IND,   "MNCC_STOP_DTMF_IND" },
62         { MNCC_STOP_DTMF_RSP,   "MNCC_STOP_DTMF_RSP" },
63         { MNCC_MODIFY_REQ,      "MNCC_MODIFY_REQ" },
64         { MNCC_MODIFY_IND,      "MNCC_MODIFY_IND" },
65         { MNCC_MODIFY_RSP,      "MNCC_MODIFY_RSP" },
66         { MNCC_MODIFY_CNF,      "MNCC_MODIFY_CNF" },
67         { MNCC_MODIFY_REJ,      "MNCC_MODIFY_REJ" },
68         { MNCC_HOLD_IND,        "MNCC_HOLD_IND" },
69         { MNCC_HOLD_CNF,        "MNCC_HOLD_CNF" },
70         { MNCC_HOLD_REJ,        "MNCC_HOLD_REJ" },
71         { MNCC_RETRIEVE_IND,    "MNCC_RETRIEVE_IND" },
72         { MNCC_RETRIEVE_CNF,    "MNCC_RETRIEVE_CNF" },
73         { MNCC_RETRIEVE_REJ,    "MNCC_RETRIEVE_REJ" },
74         { MNCC_USERINFO_REQ,    "MNCC_USERINFO_REQ" },
75         { MNCC_USERINFO_IND,    "MNCC_USERINFO_IND" },
76         { MNCC_REJ_REQ,         "MNCC_REJ_REQ" },
77         { MNCC_REJ_IND,         "MNCC_REJ_IND" },
78         { MNCC_PROGRESS_IND,    "MNCC_PROGRESS_IND" },
79         { MNCC_CALL_PROC_IND,   "MNCC_CALL_PROC_IND" },
80         { MNCC_CALL_CONF_REQ,   "MNCC_CALL_CONF_REQ" },
81         { MNCC_START_DTMF_REQ,  "MNCC_START_DTMF_REQ" },
82         { MNCC_STOP_DTMF_REQ,   "MNCC_STOP_DTMF_REQ" },
83         { MNCC_HOLD_REQ,        "MNCC_HOLD_REQ " },
84         { MNCC_RETRIEVE_REQ,    "MNCC_RETRIEVE_REQ" },
85         { 0,                    NULL }
86 };
87
88 const char *mncc_name(int value)
89 {
90         int i = 0;
91
92         while (mncc_names[i].name) {
93                 if (mncc_names[i].msg_type == value)
94                         return mncc_names[i].name;
95                 i++;
96         }
97         return "unknown";
98 }
99
100 static int mncc_send(struct lcr_gsm *lcr_gsm, int msg_type, void *data);
101
102 /*
103  * create and send mncc message
104  */
105 struct gsm_mncc *create_mncc(int msg_type, unsigned int callref)
106 {
107         struct gsm_mncc *mncc;
108
109         mncc = (struct gsm_mncc *)MALLOC(sizeof(struct gsm_mncc));
110         mncc->msg_type = msg_type;
111         mncc->callref = callref;
112         return (mncc);
113 }
114 int send_and_free_mncc(struct lcr_gsm *lcr_gsm, unsigned int msg_type, void *data)
115 {
116         int ret = 0;
117
118         if (lcr_gsm) {
119                 ret = mncc_send(lcr_gsm, msg_type, data);
120         }
121         free(data);
122
123         return ret;
124 }
125
126 static int delete_event(struct lcr_work *work, void *instance, int index);
127
128 /*
129  * constructor
130  */
131 Pgsm::Pgsm(int type, char *portname, struct port_settings *settings, struct interface *interface) : Port(type, portname, settings)
132 {
133         p_g_tones = 0;
134         if (interface->is_tones == IS_YES)
135                 p_g_tones = 1;
136         p_g_earlyb = 0;
137         if (interface->is_earlyb == IS_YES)
138                 p_g_earlyb = 1;
139         p_g_rtp_bridge = 0;
140         if (interface->rtp_bridge)
141                 p_g_rtp_bridge = 1;
142         memset(&p_g_samples, 0, sizeof(p_g_samples));
143         SCPY(p_g_interface_name, interface->name); 
144         p_callerinfo.itype = (interface->extension)?INFO_ITYPE_ISDN_EXTENSION:INFO_ITYPE_ISDN;
145         memset(&p_g_delete, 0, sizeof(p_g_delete));
146         add_work(&p_g_delete, delete_event, this, 0);
147         p_g_lcr_gsm = NULL;
148         p_g_callref = 0;
149         p_g_mode = 0;
150         p_g_gsm_b_sock = -1;
151         p_g_gsm_b_index = -1;
152         p_g_gsm_b_active = 0;
153         p_g_notify_pending = NULL;
154         p_g_setup_pending = NULL;
155         p_g_connect_pending = NULL;
156         p_g_decoder = gsm_audio_create();
157         p_g_encoder = gsm_audio_create();
158         if (!p_g_encoder || !p_g_decoder) {
159                 PERROR("Failed to create GSM audio codec instance\n");
160                 trigger_work(&p_g_delete);
161         }
162         p_g_rxpos = 0;
163         p_g_tch_connected = 0;
164
165         PDEBUG(DEBUG_GSM, "Created new GSMPort(%s).\n", portname);
166 }
167
168 /*
169  * destructor
170  */
171 Pgsm::~Pgsm()
172 {
173         PDEBUG(DEBUG_GSM, "Destroyed GSM process(%s).\n", p_name);
174
175         del_work(&p_g_delete);
176
177         /* remove queued message */
178         if (p_g_notify_pending)
179                 message_free(p_g_notify_pending);
180         if (p_g_setup_pending)
181                 message_free(p_g_setup_pending);
182         if (p_g_connect_pending)
183                 message_free(p_g_connect_pending);
184
185         /* close codec */
186         if (p_g_encoder)
187                 gsm_audio_destroy(p_g_encoder);
188         if (p_g_decoder)
189                 gsm_audio_destroy(p_g_decoder);
190 }
191
192
193 /* receive encoded frame from gsm */
194 void Pgsm::frame_receive(void *arg)
195 {
196         struct gsm_data_frame *frame = (struct gsm_data_frame *)arg;
197         unsigned char data[160];
198         int i;
199
200         if (!p_g_decoder)
201                 return;
202
203         if (frame->msg_type != GSM_TCHF_BAD_FRAME) {
204                 if ((frame->data[0]>>4) != 0xd)
205                         PERROR("received GSM frame with wrong magig 0x%x\n", frame->data[0]>>4);
206         
207                 /* decode */
208                 gsm_audio_decode(p_g_decoder, frame->data, p_g_samples);
209                 for (i = 0; i < 160; i++) {
210                         data[i] = audio_s16_to_law[p_g_samples[i] & 0xffff];
211                 }
212         } else if (p_echotest) {
213                 /* beep on bad frame */
214                 for (i = 0; i < 160; i++) {
215                         if ((i & 3) > 2)
216                                 p_g_samples[i] = 15000;
217                         else
218                                 p_g_samples[i] = -15000;
219                         data[i] = audio_s16_to_law[p_g_samples[i] & 0xffff];
220                 }
221         } else {
222                 /* repeat on bad frame */
223                 for (i = 0; i < 160; i++) {
224                         p_g_samples[i] = (p_g_samples[i] * 14) >> 4;
225                         data[i] = audio_s16_to_law[p_g_samples[i] & 0xffff];
226                 }
227         }
228
229         /* local echo */
230         if (p_echotest)
231                 bridge_rx(data, 160);
232
233         /* send to remote*/
234         bridge_tx(data, 160);
235 }
236
237 /* send traffic to gsm */
238 int Pgsm::bridge_rx(unsigned char *data, int len)
239 {
240         if (p_tone_name[0])
241                 return -EINVAL;
242
243         return audio_send(data, len);
244 }
245
246 int Pgsm::audio_send(unsigned char *data, int len)
247 {
248         unsigned char frame[33];
249
250         /* encoder init failed */
251         if (!p_g_encoder)
252                 return -EINVAL;
253
254         /* (currently) not connected, so don't flood tch! */
255         if (!p_g_tch_connected)
256                 return -EINVAL;
257
258         /* write to rx buffer */
259         while(len--) {
260                 p_g_rxdata[p_g_rxpos++] = audio_law_to_s32[*data++];
261                 if (p_g_rxpos == 160) {
262                         p_g_rxpos = 0;
263
264                         /* encode data */
265                         gsm_audio_encode(p_g_encoder, p_g_rxdata, frame);
266                         frame_send(frame);
267                 }
268         }
269
270         return 0;
271 }
272
273 void Pgsm::frame_send(void *_frame)
274 {
275         unsigned char buffer[sizeof(struct gsm_data_frame) + 33];
276         struct gsm_data_frame *frame = (struct gsm_data_frame *)buffer;
277         
278         frame->msg_type = GSM_TCHF_FRAME;
279         frame->callref = p_g_callref;
280         memcpy(frame->data, _frame, 33);
281
282         if (p_g_lcr_gsm) {
283                 mncc_send(p_g_lcr_gsm, frame->msg_type, frame);
284         }
285 }
286
287 /*
288  * create trace
289  */
290 void gsm_trace_header(const char *interface_name, class Pgsm *port, unsigned int msg_type, int direction)
291 {
292         char msgtext[64];
293         struct interface *interface = interface_first;
294
295         interface = getinterfacebyname(interface_name);
296         if (!interface)
297                 return;
298
299         /* select message and primitive text */
300         SCPY(msgtext, mncc_name(msg_type));
301
302         /* add direction */
303         if (port) {
304                 switch(port->p_type) {
305                 case PORT_TYPE_GSM_BS_OUT:
306                 case PORT_TYPE_GSM_BS_IN:
307                         SCAT(msgtext, " LCR<->BSC");
308                         break;
309                 case PORT_TYPE_GSM_MS_OUT:
310                 case PORT_TYPE_GSM_MS_IN:
311                         SCAT(msgtext, " LCR<->MS");
312                         break;
313                 }
314         } else
315                 SCAT(msgtext, " ----");
316
317         /* init trace with given values */
318         start_trace(0,
319                     interface,
320                     port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype, options.national, options.international):NULL,
321                     port?port->p_dialinginfo.id:NULL,
322                     direction,
323                     CATEGORY_CH,
324                     port?port->p_serial:0,
325                     msgtext);
326 }
327
328 /* PROCEEDING INDICATION */
329 void Pgsm::call_conf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
330 {
331         struct gsm_mncc *mode;
332
333         gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
334         if (mncc->fields & MNCC_F_CAUSE) {
335                 add_trace("cause", "coding", "%d", mncc->cause.coding);
336                 add_trace("cause", "location", "%", mncc->cause.location);
337                 add_trace("cause", "value", "%", mncc->cause.value);
338         }
339         end_trace();
340
341         /* modify lchan to GSM codec V1 */
342         gsm_trace_header(p_g_interface_name, this, MNCC_LCHAN_MODIFY, DIRECTION_OUT);
343         mode = create_mncc(MNCC_LCHAN_MODIFY, p_g_callref);
344         mode->lchan_mode = 0x01; /* GSM V1 */
345         mode->lchan_type = 0x02;
346         add_trace("mode", NULL, "0x%02x", mode->lchan_mode);
347         end_trace();
348         send_and_free_mncc(p_g_lcr_gsm, mode->msg_type, mode);
349
350 }
351
352 /* CALL PROCEEDING INDICATION */
353 void Pgsm::call_proc_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
354 {
355         struct lcr_msg *message;
356         struct gsm_mncc *frame;
357
358         gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
359         end_trace();
360
361         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_PROCEEDING);
362         message_put(message);
363
364         new_state(PORT_STATE_OUT_PROCEEDING);
365
366         if (p_g_earlyb && !p_g_tch_connected) { /* only if ... */
367                 gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
368                 end_trace();
369                 frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
370                 send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
371                 p_g_tch_connected = 1;
372         }
373 }
374
375 /* ALERTING INDICATION */
376 void Pgsm::alert_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
377 {
378         struct lcr_msg *message;
379         struct gsm_mncc *frame;
380
381         gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
382         end_trace();
383
384         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_ALERTING);
385         message_put(message);
386
387         new_state(PORT_STATE_OUT_ALERTING);
388
389         if (p_g_earlyb && !p_g_tch_connected) { /* only if ... */
390                 gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
391                 end_trace();
392                 frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
393                 send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
394                 p_g_tch_connected = 1;
395         }
396 }
397
398 /* CONNECT INDICATION */
399 void Pgsm::setup_cnf(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
400 {
401         struct gsm_mncc *resp, *frame;
402         struct lcr_msg *message;
403
404         SCPY(p_connectinfo.id, mncc->connected.number);
405         SCPY(p_connectinfo.imsi, mncc->imsi);
406         p_connectinfo.present = INFO_PRESENT_ALLOWED;
407         p_connectinfo.screen = INFO_SCREEN_NETWORK;
408         p_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
409         SCPY(p_connectinfo.interface, p_g_interface_name);
410
411         gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
412         if (p_connectinfo.id[0])
413                 add_trace("connect", "number", "%s", p_connectinfo.id);
414         else if (mncc->imsi[0])
415                 SPRINT(p_connectinfo.id, "imsi-%s", p_connectinfo.imsi);
416         if (mncc->imsi[0])
417                 add_trace("connect", "imsi", "%s", p_connectinfo.imsi);
418         end_trace();
419
420         /* send resp */
421         gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_COMPL_REQ, DIRECTION_OUT);
422         resp = create_mncc(MNCC_SETUP_COMPL_REQ, p_g_callref);
423         end_trace();
424         send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
425
426         new_state(PORT_STATE_CONNECT);
427
428         if (!p_g_tch_connected) { /* only if ... */
429                 gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
430                 end_trace();
431                 frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
432                 send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
433                 p_g_tch_connected = 1;
434         }
435
436         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CONNECT);
437         memcpy(&message->param.connectinfo, &p_connectinfo, sizeof(struct connect_info));
438         message->param.connectinfo.rtpinfo.payload_type = 3; /* FIXME: receive payload type from peer */
439
440         if (p_g_rtp_bridge) {
441                 struct gsm_mncc_rtp *rtp;
442
443                 PDEBUG(DEBUG_GSM, "Request RTP peer info, before forwarding connect msg\n");
444                 p_g_connect_pending = message;
445                 rtp = (struct gsm_mncc_rtp *) create_mncc(MNCC_RTP_CREATE, p_g_callref);
446                 send_and_free_mncc(p_g_lcr_gsm, rtp->msg_type, rtp);
447         } else
448                 message_put(message);
449 }
450
451 /* CONNECT ACK INDICATION */
452 void Pgsm::setup_compl_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
453 {
454         struct gsm_mncc *frame;
455
456         gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
457         end_trace();
458
459         new_state(PORT_STATE_CONNECT);
460
461         if (!p_g_tch_connected) { /* only if ... */
462                 gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
463                 end_trace();
464                 frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
465                 send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
466                 p_g_tch_connected = 1;
467         }
468 }
469
470 /* DISCONNECT INDICATION */
471 void Pgsm::disc_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
472 {
473         struct lcr_msg *message;
474         int cause = 16, location = 0;
475         struct gsm_mncc *resp;
476
477         gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
478         if (mncc->fields & MNCC_F_CAUSE) {
479                 location = mncc->cause.location;
480                 cause = mncc->cause.value;
481                 add_trace("cause", "coding", "%d", mncc->cause.coding);
482                 add_trace("cause", "location", "%d", location);
483                 add_trace("cause", "value", "%d", cause);
484         }
485         end_trace();
486
487         /* send release */
488         resp = create_mncc(MNCC_REL_REQ, p_g_callref);
489         gsm_trace_header(p_g_interface_name, this, MNCC_REL_REQ, DIRECTION_OUT);
490 #if 0
491         resp->fields |= MNCC_F_CAUSE;
492         resp->cause.coding = 3;
493         resp->cause.location = 1;
494         resp->cause.value = cause;
495         add_trace("cause", "coding", "%d", resp->cause.coding);
496         add_trace("cause", "location", "%d", resp->cause.location);
497         add_trace("cause", "value", "%d", resp->cause.value);
498 #endif
499         end_trace();
500         send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
501
502         /* sending release to endpoint */
503         while(p_epointlist) {
504                 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
505                 message->param.disconnectinfo.cause = cause;
506                 message->param.disconnectinfo.location = location;
507                 message_put(message);
508                 /* remove epoint */
509                 free_epointlist(p_epointlist);
510         }
511         new_state(PORT_STATE_RELEASE);
512         trigger_work(&p_g_delete);
513 }
514
515 /* CC_RELEASE INDICATION */
516 void Pgsm::rel_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
517 {
518         int location = 0, cause = 16;
519         struct lcr_msg *message;
520
521         gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
522         if (mncc->fields & MNCC_F_CAUSE) {
523                 location = mncc->cause.location;
524                 cause = mncc->cause.value;
525                 add_trace("cause", "coding", "%d", mncc->cause.coding);
526                 add_trace("cause", "location", "%d", mncc->cause.location);
527                 add_trace("cause", "value", "%d", mncc->cause.value);
528         }
529         end_trace();
530
531         /* sending release to endpoint */
532         while(p_epointlist) {
533                 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
534                 message->param.disconnectinfo.cause = cause;
535                 message->param.disconnectinfo.location = location;
536                 message_put(message);
537                 /* remove epoint */
538                 free_epointlist(p_epointlist);
539         }
540         new_state(PORT_STATE_RELEASE);
541         trigger_work(&p_g_delete);
542 }
543
544 /* NOTIFY INDICATION */
545 void Pgsm::notify_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
546 {
547         struct lcr_msg *message;
548
549         gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
550         add_trace("notify", NULL, "%d", mncc->notify);
551         end_trace();
552
553         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
554         message->param.notifyinfo.notify = mncc->notify;
555         message_put(message);
556 }
557
558 /* MESSAGE_NOTIFY */
559 void Pgsm::message_notify(unsigned int epoint_id, int message_id, union parameter *param)
560 {
561         struct gsm_mncc *mncc;
562         int notify;
563
564 //      printf("if = %d\n", param->notifyinfo.notify);
565         if (param->notifyinfo.notify>INFO_NOTIFY_NONE) {
566                 notify = param->notifyinfo.notify & 0x7f;
567                 if (p_state!=PORT_STATE_CONNECT /*&& p_state!=PORT_STATE_IN_PROCEEDING*/ && p_state!=PORT_STATE_IN_ALERTING) {
568                         /* queue notification */
569                         if (p_g_notify_pending)
570                                 message_free(p_g_notify_pending);
571                         p_g_notify_pending = message_create(ACTIVE_EPOINT(p_epointlist), p_serial, EPOINT_TO_PORT, message_id);
572                         memcpy(&p_g_notify_pending->param, param, sizeof(union parameter));
573                 } else {
574                         /* sending notification */
575                         gsm_trace_header(p_g_interface_name, this, MNCC_NOTIFY_REQ, DIRECTION_OUT);
576                         add_trace("notify", NULL, "%d", notify);
577                         end_trace();
578                         mncc = create_mncc(MNCC_NOTIFY_REQ, p_g_callref);
579                         mncc->notify = notify;
580                         send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
581                 }
582         }
583 }
584
585 /* RTP create indication */
586 void Pgsm::rtp_create_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
587 {
588         struct gsm_mncc_rtp *rtp = (struct gsm_mncc_rtp *) mncc;
589
590         /* send queued setup, as we received remote RTP info */
591         if (p_g_setup_pending) {
592                 struct lcr_msg *message;
593
594                 message = p_g_setup_pending;
595                 PDEBUG(DEBUG_GSM, "Got RTP peer info (%08x,%d) forwarding setup\n", rtp->ip, rtp->port);
596                 message->param.setup.rtpinfo.ip = rtp->ip;
597                 message->param.setup.rtpinfo.port = rtp->port;
598                 message_put(message);
599                 p_g_setup_pending = NULL;
600         }
601         if (p_g_connect_pending) {
602                 struct gsm_mncc_rtp *nrtp;
603
604                 PDEBUG(DEBUG_GSM, "Got RTP peer info (%08x,%d) connecting RTP... \n", rtp->ip, rtp->port);
605                 nrtp = (struct gsm_mncc_rtp *) create_mncc(MNCC_RTP_CONNECT, p_g_callref);
606                 nrtp->ip = p_g_rtp_ip_remote;
607                 nrtp->port = p_g_rtp_port_remote;
608                 send_and_free_mncc(p_g_lcr_gsm, nrtp->msg_type, nrtp);
609         }
610 }
611
612 /* RTP connect indication */
613 void Pgsm::rtp_connect_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
614 {
615         struct lcr_msg *message;
616         struct gsm_mncc_rtp *rtp = (struct gsm_mncc_rtp *) mncc;
617
618         if (p_g_connect_pending) {
619                 message = p_g_connect_pending;
620                 PDEBUG(DEBUG_GSM, "Got RTP peer info (%08x,%d) forwarding connect\n", rtp->ip, rtp->port);
621                 message->param.connectinfo.rtpinfo.ip = rtp->ip;
622                 message->param.connectinfo.rtpinfo.port = rtp->port;
623                 message_put(message);
624                 p_g_connect_pending = NULL;
625         }
626 }
627
628 /* MESSAGE_PROGRESS */
629 void Pgsm::message_progress(unsigned int epoint_id, int message_id, union parameter *param)
630 {
631         if (param->progressinfo.progress == 8) {
632                 PDEBUG(DEBUG_GSM, "Remote provides tones for us\n");
633                 p_g_tones = 1;
634         }
635
636         if (param->progressinfo.rtpinfo.port) {
637                 struct gsm_mncc_rtp *rtp;
638
639                 PDEBUG(DEBUG_GSM, "CONNECT with RTP peer info, sent to BSC (%08x,%d)\n", param->progressinfo.rtpinfo.ip, param->progressinfo.rtpinfo.port);
640                 rtp = (struct gsm_mncc_rtp *) create_mncc(MNCC_RTP_CONNECT, p_g_callref);
641                 rtp->ip = param->progressinfo.rtpinfo.ip;
642                 rtp->port = param->progressinfo.rtpinfo.port;
643                 send_and_free_mncc(p_g_lcr_gsm, rtp->msg_type, rtp);
644         }
645 }
646
647 /* MESSAGE_ALERTING */
648 void Pgsm::message_alerting(unsigned int epoint_id, int message_id, union parameter *param)
649 {
650         struct gsm_mncc *mncc;
651
652         /* send alert */
653         gsm_trace_header(p_g_interface_name, this, MNCC_ALERT_REQ, DIRECTION_OUT);
654         mncc = create_mncc(MNCC_ALERT_REQ, p_g_callref);
655         if (p_g_tones) {
656                 mncc->fields |= MNCC_F_PROGRESS;
657                 mncc->progress.coding = 3; /* GSM */
658                 mncc->progress.location = 1;
659                 mncc->progress.descr = 8;
660                 add_trace("progress", "coding", "%d", mncc->progress.coding);
661                 add_trace("progress", "location", "%d", mncc->progress.location);
662                 add_trace("progress", "descr", "%d", mncc->progress.descr);
663         }
664         end_trace();
665         send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
666
667         new_state(PORT_STATE_IN_ALERTING);
668
669         if (p_g_tones && !p_g_tch_connected) { /* only if ... */
670                 gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
671                 end_trace();
672                 mncc = create_mncc(MNCC_FRAME_RECV, p_g_callref);
673                 send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
674                 p_g_tch_connected = 1;
675         }
676 }
677
678 /* MESSAGE_CONNECT */
679 void Pgsm::message_connect(unsigned int epoint_id, int message_id, union parameter *param)
680 {
681         struct gsm_mncc *mncc;
682
683         /* copy connected information */
684         memcpy(&p_connectinfo, &param->connectinfo, sizeof(p_connectinfo));
685         /* screen outgoing caller id */
686         do_screen(1, p_connectinfo.id, sizeof(p_connectinfo.id), &p_connectinfo.ntype, &p_connectinfo.present, p_g_interface_name);
687
688         /* send connect */
689         mncc = create_mncc(MNCC_SETUP_RSP, p_g_callref);
690         gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_RSP, DIRECTION_OUT);
691         /* caller information */
692         mncc->fields |= MNCC_F_CONNECTED;
693         mncc->connected.plan = 1;
694         switch (p_callerinfo.ntype) {
695                 case INFO_NTYPE_UNKNOWN:
696                 mncc->connected.type = 0x0;
697                 break;
698                 case INFO_NTYPE_INTERNATIONAL:
699                 mncc->connected.type = 0x1;
700                 break;
701                 case INFO_NTYPE_NATIONAL:
702                 mncc->connected.type = 0x2;
703                 break;
704                 case INFO_NTYPE_SUBSCRIBER:
705                 mncc->connected.type = 0x4;
706                 break;
707                 default: /* INFO_NTYPE_NOTPRESENT */
708                 mncc->fields &= ~MNCC_F_CONNECTED;
709                 break;
710         }
711         switch (p_callerinfo.screen) {
712                 case INFO_SCREEN_USER:
713                 mncc->connected.screen = 0;
714                 break;
715                 default: /* INFO_SCREEN_NETWORK */
716                 mncc->connected.screen = 3;
717                 break;
718         }
719         switch (p_callerinfo.present) {
720                 case INFO_PRESENT_ALLOWED:
721                 mncc->connected.present = 0;
722                 break;
723                 case INFO_PRESENT_RESTRICTED:
724                 mncc->connected.present = 1;
725                 break;
726                 default: /* INFO_PRESENT_NOTAVAIL */
727                 mncc->connected.present = 2;
728                 break;
729         }
730         if (mncc->fields & MNCC_F_CONNECTED) {
731                 SCPY(mncc->connected.number, p_connectinfo.id);
732                 add_trace("connected", "type", "%d", mncc->connected.type);
733                 add_trace("connected", "plan", "%d", mncc->connected.plan);
734                 add_trace("connected", "present", "%d", mncc->connected.present);
735                 add_trace("connected", "screen", "%d", mncc->connected.screen);
736                 add_trace("connected", "number", "%s", mncc->connected.number);
737         }
738         end_trace();
739         send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
740
741         new_state(PORT_STATE_CONNECT_WAITING);
742
743         if (param->connectinfo.rtpinfo.port) {
744                 struct gsm_mncc_rtp *rtp;
745
746                 PDEBUG(DEBUG_GSM, "CONNECT with RTP peer info, sent to BSC (%08x,%d)\n", param->connectinfo.rtpinfo.ip, param->connectinfo.rtpinfo.port);
747                 rtp = (struct gsm_mncc_rtp *) create_mncc(MNCC_RTP_CONNECT, p_g_callref);
748                 rtp->ip = param->connectinfo.rtpinfo.ip;
749                 rtp->port = param->connectinfo.rtpinfo.port;
750                 send_and_free_mncc(p_g_lcr_gsm, rtp->msg_type, rtp);
751         }
752
753 }
754
755 /* MESSAGE_DISCONNECT */
756 void Pgsm::message_disconnect(unsigned int epoint_id, int message_id, union parameter *param)
757 {
758         struct gsm_mncc *mncc;
759
760         /* send disconnect */
761         mncc = create_mncc(MNCC_DISC_REQ, p_g_callref);
762         gsm_trace_header(p_g_interface_name, this, MNCC_DISC_REQ, DIRECTION_OUT);
763         if (p_g_tones) {
764                 mncc->fields |= MNCC_F_PROGRESS;
765                 mncc->progress.coding = 3; /* GSM */
766                 mncc->progress.location = 1;
767                 mncc->progress.descr = 8;
768                 add_trace("progress", "coding", "%d", mncc->progress.coding);
769                 add_trace("progress", "location", "%d", mncc->progress.location);
770                 add_trace("progress", "descr", "%d", mncc->progress.descr);
771         }
772         mncc->fields |= MNCC_F_CAUSE;
773         mncc->cause.coding = 3;
774         mncc->cause.location = param->disconnectinfo.location;
775         mncc->cause.value = param->disconnectinfo.cause;
776         add_trace("cause", "coding", "%d", mncc->cause.coding);
777         add_trace("cause", "location", "%d", mncc->cause.location);
778         add_trace("cause", "value", "%d", mncc->cause.value);
779         end_trace();
780         send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
781
782         new_state(PORT_STATE_OUT_DISCONNECT);
783
784         if (p_g_tones && !p_g_tch_connected) { /* only if ... */
785                 gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
786                 end_trace();
787                 mncc = create_mncc(MNCC_FRAME_RECV, p_g_callref);
788                 send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
789                 p_g_tch_connected = 1;
790         }
791 }
792
793
794 /* MESSAGE_RELEASE */
795 void Pgsm::message_release(unsigned int epoint_id, int message_id, union parameter *param)
796 {
797         struct gsm_mncc *mncc;
798
799         /* send release */
800         mncc = create_mncc(MNCC_REL_REQ, p_g_callref);
801         gsm_trace_header(p_g_interface_name, this, MNCC_REL_REQ, DIRECTION_OUT);
802         mncc->fields |= MNCC_F_CAUSE;
803         mncc->cause.coding = 3;
804         mncc->cause.location = param->disconnectinfo.location;
805         mncc->cause.value = param->disconnectinfo.cause;
806         add_trace("cause", "coding", "%d", mncc->cause.coding);
807         add_trace("cause", "location", "%d", mncc->cause.location);
808         add_trace("cause", "value", "%d", mncc->cause.value);
809         end_trace();
810         send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
811
812         new_state(PORT_STATE_RELEASE);
813         trigger_work(&p_g_delete);
814         return;
815 }
816
817 /*
818  * endpoint sends messages to the port
819  */
820 int Pgsm::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
821 {
822         int ret = 0;
823
824         if (Port::message_epoint(epoint_id, message_id, param))
825                 return 1;
826
827         switch(message_id) {
828                 case MESSAGE_NOTIFY: /* display and notifications */
829                 ret = 1;
830                 message_notify(epoint_id, message_id, param);
831                 break;
832
833 //              case MESSAGE_FACILITY: /* facility message */
834 //              message_facility(epoint_id, message_id, param);
835 //              break;
836
837                 case MESSAGE_PROCEEDING: /* message not handles */
838                 ret = 1;
839                 break;
840
841                 case MESSAGE_PROGRESS:
842                 ret = 1;
843                 message_progress(epoint_id, message_id, param);
844                 break;
845
846                 case MESSAGE_ALERTING: /* call of endpoint is ringing */
847                 ret = 1;
848                 if (p_state!=PORT_STATE_IN_PROCEEDING)
849                         break;
850                 message_alerting(epoint_id, message_id, param);
851                 if (p_g_notify_pending) {
852                         /* send pending notify message during connect */
853                         message_notify(ACTIVE_EPOINT(p_epointlist), p_g_notify_pending->type, &p_g_notify_pending->param);
854                         message_free(p_g_notify_pending);
855                         p_g_notify_pending = NULL;
856                 }
857                 break;
858
859                 case MESSAGE_CONNECT: /* call of endpoint is connected */
860                 ret = 1;
861                 if (p_state!=PORT_STATE_IN_PROCEEDING
862                  && p_state!=PORT_STATE_IN_ALERTING)
863                         break;
864                 message_connect(epoint_id, message_id, param);
865                 if (p_g_notify_pending) {
866                         /* send pending notify message during connect */
867                         message_notify(ACTIVE_EPOINT(p_epointlist), p_g_notify_pending->type, &p_g_notify_pending->param);
868                         message_free(p_g_notify_pending);
869                         p_g_notify_pending = NULL;
870                 }
871                 break;
872
873                 case MESSAGE_DISCONNECT: /* call has been disconnected */
874                 ret = 1;
875                 if (p_state!=PORT_STATE_IN_PROCEEDING
876                  && p_state!=PORT_STATE_IN_ALERTING
877                  && p_state!=PORT_STATE_OUT_SETUP
878                  && p_state!=PORT_STATE_OUT_OVERLAP
879                  && p_state!=PORT_STATE_OUT_PROCEEDING
880                  && p_state!=PORT_STATE_OUT_ALERTING
881                  && p_state!=PORT_STATE_CONNECT
882                  && p_state!=PORT_STATE_CONNECT_WAITING)
883                         break;
884                 message_disconnect(epoint_id, message_id, param);
885                 break;
886
887                 case MESSAGE_RELEASE: /* release isdn port */
888                 ret = 1;
889                 if (p_state==PORT_STATE_RELEASE)
890                         break;
891                 message_release(epoint_id, message_id, param);
892                 break;
893
894         }
895
896         return ret;
897 }
898
899 /* deletes only if l3id is release, otherwhise it will be triggered then */
900 static int delete_event(struct lcr_work *work, void *instance, int index)
901 {
902         class Pgsm *gsmport = (class Pgsm *)instance;
903
904         delete gsmport;
905
906         return 0;
907 }
908
909 int gsm_exit(int rc)
910 {
911         return(rc);
912 }
913
914 int gsm_init(void)
915 {
916         /* seed the PRNG */
917         srand(time(NULL));
918
919         return 0;
920 }
921
922 /*
923  * MNCC interface
924  */
925
926 static int mncc_q_enqueue(struct lcr_gsm *lcr_gsm, struct gsm_mncc *mncc, unsigned int len)
927 {
928         struct mncc_q_entry *qe;
929
930         qe = (struct mncc_q_entry *) MALLOC(sizeof(*qe)+sizeof(*mncc)+len);
931         if (!qe)
932                 return -ENOMEM;
933
934         qe->next = NULL;
935         qe->len = len;
936         memcpy(qe->data, mncc, len);
937
938         /* in case of empty list ... */
939         if (!lcr_gsm->mncc_q_hd && !lcr_gsm->mncc_q_tail) {
940                 /* the list head and tail both point to the new qe */
941                 lcr_gsm->mncc_q_hd = lcr_gsm->mncc_q_tail = qe;
942         } else {
943                 /* append to tail of list */
944                 lcr_gsm->mncc_q_tail->next = qe;
945                 lcr_gsm->mncc_q_tail = qe;
946         }
947
948         lcr_gsm->mncc_lfd.when |= LCR_FD_WRITE;
949
950         return 0;
951 }
952
953 static struct mncc_q_entry *mncc_q_dequeue(struct lcr_gsm *lcr_gsm)
954 {
955         struct mncc_q_entry *qe = lcr_gsm->mncc_q_hd;
956         if (!qe)
957                 return NULL;
958
959         /* dequeue the successfully sent message */
960         lcr_gsm->mncc_q_hd = qe->next;
961         if (!qe)
962                 return NULL;
963         if (qe == lcr_gsm->mncc_q_tail)
964                 lcr_gsm->mncc_q_tail = NULL;
965
966         return qe;
967 }
968
969 /* routine called by LCR code if it wants to send a message to OpenBSC */
970 static int mncc_send(struct lcr_gsm *lcr_gsm, int msg_type, void *data)
971 {
972         int len = 0;
973
974         /* FIXME: the caller should provide this */
975         switch (msg_type) {
976         case GSM_TCHF_FRAME:
977                 len = sizeof(struct gsm_data_frame) + 33;
978                 break;
979         default:
980                 len = sizeof(struct gsm_mncc);
981                 break;
982         }
983                 
984         return mncc_q_enqueue(lcr_gsm, (struct gsm_mncc *)data, len);
985 }
986
987 /* close MNCC socket */
988 static int mncc_fd_close(struct lcr_gsm *lcr_gsm, struct lcr_fd *lfd)
989 {
990         class Port *port;
991         class Pgsm *pgsm = NULL;
992         struct lcr_msg *message;
993
994         PERROR("Lost MNCC socket, retrying in %u seconds\n", SOCKET_RETRY_TIMER);
995         close(lfd->fd);
996         unregister_fd(lfd);
997         lfd->fd = -1;
998
999         /* free all the calls that were running through the MNCC interface */
1000         port = port_first;
1001         while(port) {
1002                 if ((port->p_type & PORT_CLASS_mISDN_MASK) == PORT_CLASS_GSM) {
1003                         pgsm = (class Pgsm *)port;
1004                         if (pgsm->p_g_lcr_gsm == lcr_gsm) {
1005                                 message = message_create(pgsm->p_serial, ACTIVE_EPOINT(pgsm->p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
1006                                 message->param.disconnectinfo.cause = 27; // temp. unavail.
1007                                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1008                                 message_put(message);
1009                                 pgsm->new_state(PORT_STATE_RELEASE);
1010                                 trigger_work(&pgsm->p_g_delete);
1011                         }
1012                 }
1013                 port = port->next;
1014         }
1015
1016         /* flush the queue */
1017         while (mncc_q_dequeue(lcr_gsm))
1018                 ;
1019
1020         /* start the re-connect timer */
1021         schedule_timer(&lcr_gsm->socket_retry, SOCKET_RETRY_TIMER, 0);
1022
1023         return 0;
1024 }
1025
1026 /* write to OpenBSC via MNCC socket */
1027 static int mncc_fd_write(struct lcr_fd *lfd, void *inst, int idx)
1028 {
1029         struct lcr_gsm *lcr_gsm = (struct lcr_gsm *) inst;
1030         struct mncc_q_entry *qe, *qe2;
1031         int rc;
1032
1033         while (1) {
1034                 qe = lcr_gsm->mncc_q_hd;
1035                 if (!qe) {
1036                         lfd->when &= ~LCR_FD_WRITE;
1037                         break;
1038                 }
1039                 rc = write(lfd->fd, qe->data, qe->len);
1040                 if (rc == 0)
1041                         return mncc_fd_close(lcr_gsm, lfd);
1042                 if (rc < 0)
1043                         return rc;
1044                 if (rc < (int)qe->len)
1045                         return -1;
1046                 /* dequeue the successfully sent message */
1047                 qe2 = mncc_q_dequeue(lcr_gsm);
1048                 assert(qe == qe2);
1049                 free(qe);
1050         }
1051         return 0;
1052 }
1053
1054 /* read from OpenBSC via MNCC socket */
1055 static int mncc_fd_read(struct lcr_fd *lfd, void *inst, int idx)
1056 {
1057         struct lcr_gsm *lcr_gsm = (struct lcr_gsm *) inst;
1058         int rc;
1059         static char buf[sizeof(struct gsm_mncc)+1024];
1060         struct gsm_mncc *mncc_prim = (struct gsm_mncc *) buf;
1061
1062         memset(buf, 0, sizeof(buf));
1063         rc = recv(lfd->fd, buf, sizeof(buf), 0);
1064         if (rc == 0)
1065                 return mncc_fd_close(lcr_gsm, lfd);
1066         if (rc < 0)
1067                 return rc;
1068
1069         /* Hand the MNCC message into LCR */
1070         switch (lcr_gsm->type) {
1071 #ifdef WITH_GSM_BS
1072         case LCR_GSM_TYPE_NETWORK:
1073                 return message_bsc(lcr_gsm, mncc_prim->msg_type, mncc_prim);
1074 #endif
1075 #ifdef WITH_GSM_MS
1076         case LCR_GSM_TYPE_MS:
1077                 return message_ms(lcr_gsm, mncc_prim->msg_type, mncc_prim);
1078 #endif
1079         default:
1080                 return 0;
1081         }
1082 }
1083
1084 /* file descriptor callback if we can read or write form MNCC socket */
1085 static int mncc_fd_cb(struct lcr_fd *lfd, unsigned int what, void *inst, int idx)
1086 {
1087         int rc = 0;
1088
1089         if (what & LCR_FD_READ)
1090                 rc = mncc_fd_read(lfd, inst, idx);
1091         if (rc < 0)
1092                 return rc;
1093
1094         if (what & LCR_FD_WRITE)
1095                 rc = mncc_fd_write(lfd, inst, idx);
1096
1097         return rc;
1098 }
1099
1100 int mncc_socket_retry_cb(struct lcr_timer *timer, void *inst, int index)
1101 {
1102         struct lcr_gsm *lcr_gsm = (struct lcr_gsm *) inst;
1103         int fd, rc;
1104
1105         lcr_gsm->mncc_lfd.fd = -1;
1106
1107         fd = socket(PF_UNIX, SOCK_SEQPACKET, 0);
1108         if (fd < 0) {
1109                 PERROR("Cannot create SEQPACKET socket, giving up!\n");
1110                 return fd;
1111         }
1112
1113         rc = connect(fd, (struct sockaddr *) &lcr_gsm->sun,
1114                      sizeof(lcr_gsm->sun));
1115         if (rc < 0) {
1116                 PERROR("Could not connect to MNCC socket %s, "
1117                         "retrying in %u seconds\n", lcr_gsm->sun.sun_path,
1118                         SOCKET_RETRY_TIMER);
1119                 close(fd);
1120                 schedule_timer(&lcr_gsm->socket_retry, SOCKET_RETRY_TIMER, 0);
1121         } else {
1122                 PDEBUG(DEBUG_GSM, "Connected to MNCC socket %s!\n", lcr_gsm->sun.sun_path);
1123                 lcr_gsm->mncc_lfd.fd = fd;
1124                 register_fd(&lcr_gsm->mncc_lfd, LCR_FD_READ, &mncc_fd_cb, lcr_gsm, 0);
1125         }
1126
1127         return 0;
1128 }
1129