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