Add 'prefix' parameter to 'goto' action
[lcr.git] / remote.cpp
1 /*****************************************************************************\
2 **                                                                           **
3 ** LCR                                                                       **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** mISDN remote                                                              **
9 **                                                                           **
10 \*****************************************************************************/ 
11
12 #include "main.h"
13
14 unsigned int new_remote = 1000;
15
16 /*
17  * constructor
18  */
19 Premote::Premote(int type, char *portname, struct port_settings *settings, struct interface *interface, int remote_id) : Port(type, portname, settings, interface)
20 {
21         union parameter param;
22
23         p_callerinfo.itype = (interface->extension)?INFO_ITYPE_ISDN_EXTENSION:INFO_ITYPE_ISDN;
24         p_r_ref = new_remote++;
25         SCPY(p_r_remote_app, interface->remote_app);
26         p_r_tones = (interface->is_tones == IS_YES);
27         p_r_earlyb = (interface->is_earlyb == IS_YES);
28
29         /* send new ref to remote socket */
30         memset(&param, 0, sizeof(union parameter));
31         if (type == PORT_TYPE_REMOTE_OUT)
32                 param.newref.direction = 1; /* new ref from lcr */
33         p_r_remote_id = remote_id;
34         if (admin_message_from_lcr(p_r_remote_id, p_r_ref, MESSAGE_NEWREF, &param) < 0)
35                 FATAL("No socket with remote application '%s' found, this shall not happen. because we already created one.\n", p_r_remote_app);
36
37         PDEBUG(DEBUG_PORT, "Created new RemotePort(%s).\n", portname);
38
39 }
40
41 /*
42  * destructor
43  */
44 Premote::~Premote()
45 {
46         PDEBUG(DEBUG_PORT, "Destroyed Remote process(%s).\n", p_name);
47 }
48
49 /*
50  * endpoint sends messages to the port
51  */
52 int Premote::message_epoint(unsigned int epoint_id, int message_type, union parameter *param)
53 {
54         struct epoint_list *epointlist;
55
56         if (Port::message_epoint(epoint_id, message_type, param))
57                 return 1;
58
59         switch (message_type) {
60         case MESSAGE_SETUP:
61                 struct interface *interface;
62                 interface = getinterfacebyname(p_interface_name);
63                 if (!interface) {
64                         PERROR("Cannot find interface %s.\n", p_interface_name);
65                         return 0;
66                 }
67                 /* attach only if not already */
68                 epointlist = p_epointlist;
69                 while(epointlist) {
70                         if (epointlist->epoint_id == epoint_id)
71                                 break;
72                         epointlist = epointlist->next;
73                 }
74                 if (!epointlist)
75                         epointlist_new(epoint_id);
76
77                 /* set context to pbx */
78                 if (!param->setup.dialinginfo.context[0]) {
79                         if (interface->remote_context[0])
80                                 SCPY(param->setup.dialinginfo.context, interface->remote_context);
81                         else
82                                 SCPY(param->setup.dialinginfo.context, "lcr");
83                 }
84                 memcpy(&p_dialinginfo, &param->setup.dialinginfo, sizeof(p_dialinginfo));
85                 memcpy(&p_capainfo, &param->setup.capainfo, sizeof(p_capainfo));
86                 memcpy(&p_callerinfo, &param->setup.callerinfo, sizeof(p_callerinfo));
87                 memcpy(&p_redirinfo, &param->setup.redirinfo, sizeof(p_redirinfo));
88                 /* screen */
89                 do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_interface_name);
90                 do_screen(1, p_callerinfo.id2, sizeof(p_callerinfo.id2), &p_callerinfo.ntype2, &p_callerinfo.present2, p_interface_name);
91                 do_screen(1, p_redirinfo.id, sizeof(p_redirinfo.id), &p_redirinfo.ntype, &p_redirinfo.present, p_interface_name);
92                 memcpy(&param->setup.callerinfo, &p_callerinfo, sizeof(p_callerinfo));
93                 memcpy(&param->setup.redirinfo, &p_redirinfo, sizeof(p_redirinfo));
94
95                 new_state(PORT_STATE_OUT_SETUP);
96                 break;
97
98         case MESSAGE_PROCEEDING:
99                 new_state(PORT_STATE_IN_PROCEEDING);
100                 break;
101
102         case MESSAGE_ALERTING:
103                 new_state(PORT_STATE_IN_ALERTING);
104                 break;
105
106         case MESSAGE_CONNECT:
107                 memcpy(&p_connectinfo, &param->connectinfo, sizeof(p_connectinfo));
108                 new_state(PORT_STATE_CONNECT);
109                 {
110                         union parameter newparam;
111                         memset(&newparam, 0, sizeof(union parameter));
112                         param->traffic.len = 160;
113                         admin_message_from_lcr(p_r_remote_id, p_r_ref, MESSAGE_TRAFFIC, param);
114                 }
115                 break;
116
117         case MESSAGE_DISCONNECT:
118                 new_state(PORT_STATE_OUT_DISCONNECT);
119                 break;
120
121         case MESSAGE_RELEASE:
122                 new_state(PORT_STATE_RELEASE);
123                 break;
124         }
125
126         /* look for Remote's interface */
127         if (admin_message_from_lcr(p_r_remote_id, p_r_ref, message_type, param)<0) {
128                 PERROR("No socket with remote application '%s' found, this shall not happen. Closing socket shall cause release of all remote ports.\n", p_r_remote_app);
129                 return 0;               
130         }
131
132         if (message_type == MESSAGE_RELEASE) {
133                 new_state(PORT_STATE_RELEASE);
134                 delete this;
135                 return 0;
136         }
137
138         return 0;
139 }
140
141 void Premote::message_remote(int message_type, union parameter *param)
142 {
143         class Endpoint *epoint;
144         struct lcr_msg *message;
145         struct interface *interface;
146
147         switch (message_type) {
148         case MESSAGE_TRAFFIC:
149                 if (p_dov_rx)
150                         dov_rx(param->traffic.data, param->traffic.len);
151                 /* record audio */
152                 if (p_record)
153                         record(param->traffic.data, param->traffic.len, 0); // from down
154                 if (p_tap)
155                         tap(param->traffic.data, param->traffic.len, 0); // from down
156                 bridge_tx(param->traffic.data, param->traffic.len);
157                 if (p_tone_name[0]) {
158                         read_audio(param->traffic.data, param->traffic.len);
159                         /* record audio */
160                         if (p_record)
161                                 record(param->traffic.data, param->traffic.len, 1); // from up
162                         if (p_tap)
163                                 tap(param->traffic.data, param->traffic.len, 1); // from up
164                         admin_message_from_lcr(p_r_remote_id, p_r_ref, MESSAGE_TRAFFIC, param);
165                 } else if (p_dov_tx) {
166                         /* use receeived traffic to trigger sending DOV */
167                         dov_tx(param->traffic.data, param->traffic.len);
168                         admin_message_from_lcr(p_r_remote_id, p_r_ref, MESSAGE_TRAFFIC, param);
169                 }
170                 return;
171
172         case MESSAGE_SETUP:
173                 interface = getinterfacebyname(p_interface_name);
174                 if (!interface) {
175                         PERROR("Cannot find interface %s.\n", p_interface_name);
176                         return;
177                 }
178
179                 /* enable audio path */
180                 if (interface->is_tones == IS_YES) {
181                         union parameter newparam;
182                         memset(&newparam, 0, sizeof(union parameter));
183                         admin_message_from_lcr(p_r_remote_id, p_r_ref, MESSAGE_PATTERN, &newparam);
184                         newparam.audiopath = 1;
185                         admin_message_from_lcr(p_r_remote_id, p_r_ref, MESSAGE_AUDIOPATH, &newparam);
186                 }
187
188                 /* set source interface */
189                 param->setup.callerinfo.itype = p_callerinfo.itype;
190                 SCPY(param->setup.callerinfo.interface, interface->name);
191                 
192                 /* create endpoint */
193                 if (p_epointlist)
194                         FATAL("Incoming call but already got an endpoint.\n");
195                 if (!(epoint = new Endpoint(p_serial, 0)))
196                         FATAL("No memory for Endpoint instance\n");
197                 epoint->ep_app = new_endpointapp(epoint, 0, interface->app); //incoming
198
199                 epointlist_new(epoint->ep_serial);
200
201                 memcpy(&p_dialinginfo, &param->setup.dialinginfo, sizeof(p_dialinginfo));
202                 memcpy(&p_capainfo, &param->setup.capainfo, sizeof(p_capainfo));
203                 memcpy(&p_callerinfo, &param->setup.callerinfo, sizeof(p_callerinfo));
204                 memcpy(&p_redirinfo, &param->setup.redirinfo, sizeof(p_redirinfo));
205
206                 new_state(PORT_STATE_IN_SETUP);
207                 break;
208
209         case MESSAGE_PROCEEDING:
210                 new_state(PORT_STATE_OUT_PROCEEDING);
211                 break;
212
213         case MESSAGE_ALERTING:
214                 new_state(PORT_STATE_OUT_ALERTING);
215                 break;
216
217         case MESSAGE_CONNECT:
218                 memcpy(&p_connectinfo, &param->connectinfo, sizeof(p_connectinfo));
219                 new_state(PORT_STATE_CONNECT);
220                 {
221                         union parameter newparam;
222                         memset(&newparam, 0, sizeof(union parameter));
223                         param->traffic.len = 160;
224                         admin_message_from_lcr(p_r_remote_id, p_r_ref, MESSAGE_TRAFFIC, param);
225                 }
226                 break;
227
228         case MESSAGE_DISCONNECT:
229                 new_state(PORT_STATE_IN_DISCONNECT);
230                 break;
231
232         case MESSAGE_RELEASE:
233                 new_state(PORT_STATE_RELEASE);
234                 break;
235         }
236
237         /* cannot just forward, because param is not of container "struct lcr_msg" */
238         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, message_type);
239         memcpy(&message->param, param, sizeof(message->param));
240         message_put(message);
241
242         if (message_type == MESSAGE_RELEASE) {
243                 new_state(PORT_STATE_RELEASE);
244                 delete this;
245                 return;
246         }
247 }
248
249 /* receive from remote Port instance */
250 int Premote::bridge_rx(unsigned char *data, int len)
251 {
252         union parameter newparam;
253         int l;
254         int ret;
255
256         if ((ret = Port::bridge_rx(data, len)))
257                 return ret;
258
259         /* send tones, if connected, or if early audio is enabled in proceeding/alerting state */
260         if (p_state != PORT_STATE_CONNECT
261          && !(p_r_earlyb
262           && (p_state == PORT_STATE_OUT_PROCEEDING
263            || p_state == PORT_STATE_OUT_ALERTING))
264          && !(p_r_tones
265           && (p_state == PORT_STATE_IN_PROCEEDING
266            || p_state == PORT_STATE_IN_ALERTING)))
267                 return 0;
268
269         if (p_tone_name[0])
270                 return 0;
271
272         memset(&newparam, 0, sizeof(union parameter));
273         /* split, if exeeds data size */
274         while(len) {
275                 l = (len > (int)sizeof(newparam.traffic.data)) ? sizeof(newparam.traffic.data) : len;
276                 newparam.traffic.len = l;
277                 len -= l;
278                 memcpy(newparam.traffic.data, data, l);
279                 data += l;
280                 /* record audio */
281                 if (p_record)
282                         record(data, len, 1); // from up
283                 if (p_tap)
284                         tap(data, len, 1); // from up
285                 admin_message_from_lcr(p_r_remote_id, p_r_ref, MESSAGE_TRAFFIC, &newparam);
286         }
287
288         return 0;
289 }
290
291