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