Maintain states for remote socket connections
[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)
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         SCPY(p_r_interface_name, interface->name);
27         p_r_tones = (interface->is_tones == 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_r_interface_name);
63                 if (!interface) {
64                         PERROR("Cannot find interface %s.\n", p_r_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
85                 new_state(PORT_STATE_OUT_SETUP);
86                 break;
87
88         case MESSAGE_PROCEEDING:
89                 new_state(PORT_STATE_IN_PROCEEDING);
90                 break;
91
92         case MESSAGE_ALERTING:
93                 new_state(PORT_STATE_IN_ALERTING);
94                 break;
95
96         case MESSAGE_CONNECT:
97                 new_state(PORT_STATE_CONNECT);
98                 break;
99
100         case MESSAGE_DISCONNECT:
101                 new_state(PORT_STATE_OUT_DISCONNECT);
102                 break;
103
104         case MESSAGE_RELEASE:
105                 new_state(PORT_STATE_RELEASE);
106                 break;
107         }
108
109         /* look for Remote's interface */
110         if (admin_message_from_lcr(p_r_remote_id, p_r_ref, message_type, param)<0) {
111                 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);
112                 return 0;               
113         }
114
115         if (message_type == MESSAGE_RELEASE) {
116                 new_state(PORT_STATE_RELEASE);
117                 delete this;
118                 return 0;
119         }
120
121         return 0;
122 }
123
124 void Premote::message_remote(int message_type, union parameter *param)
125 {
126         class Endpoint *epoint;
127         struct lcr_msg *message;
128         struct interface *interface;
129
130         switch (message_type) {
131         case MESSAGE_TRAFFIC:
132                 bridge_tx(param->traffic.data, param->traffic.len);
133                 break;
134
135         case MESSAGE_SETUP:
136                 interface = getinterfacebyname(p_r_interface_name);
137                 if (!interface) {
138                         PERROR("Cannot find interface %s.\n", p_r_interface_name);
139                         return;
140                 }
141
142                 /* enable audio path */
143                 if (interface->is_tones == IS_YES) {
144                         union parameter newparam;
145                         memset(&newparam, 0, sizeof(union parameter));
146                         admin_message_from_lcr(p_r_remote_id, p_r_ref, MESSAGE_PATTERN, &newparam);
147                         newparam.audiopath = 1;
148                         admin_message_from_lcr(p_r_remote_id, p_r_ref, MESSAGE_AUDIOPATH, &newparam);
149                 }
150
151                 /* set source interface */
152                 param->setup.callerinfo.itype = p_callerinfo.itype;
153                 SCPY(param->setup.callerinfo.interface, interface->name);
154                 
155                 /* create endpoint */
156                 if (p_epointlist)
157                         FATAL("Incoming call but already got an endpoint.\n");
158                 if (!(epoint = new Endpoint(p_serial, 0)))
159                         FATAL("No memory for Endpoint instance\n");
160                 epoint->ep_app = new_endpointapp(epoint, 0, interface->app); //incoming
161
162                 epointlist_new(epoint->ep_serial);
163
164                 new_state(PORT_STATE_IN_SETUP);
165                 break;
166
167         case MESSAGE_PROCEEDING:
168                 new_state(PORT_STATE_OUT_PROCEEDING);
169                 break;
170
171         case MESSAGE_ALERTING:
172                 new_state(PORT_STATE_OUT_ALERTING);
173                 break;
174
175         case MESSAGE_CONNECT:
176                 new_state(PORT_STATE_CONNECT);
177                 break;
178
179         case MESSAGE_DISCONNECT:
180                 new_state(PORT_STATE_IN_DISCONNECT);
181                 break;
182
183         case MESSAGE_RELEASE:
184                 new_state(PORT_STATE_RELEASE);
185                 break;
186         }
187
188         /* cannot just forward, because param is not of container "struct lcr_msg" */
189         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, message_type);
190         memcpy(&message->param, param, sizeof(message->param));
191         message_put(message);
192
193         if (message_type == MESSAGE_RELEASE) {
194                 new_state(PORT_STATE_RELEASE);
195                 delete this;
196                 return;
197         }
198 }
199
200 /* receive from remote Port instance */
201 int Premote::bridge_rx(unsigned char *data, int len)
202 {
203         union parameter newparam;
204         int l;
205
206         /* don't send tones, if not enabled or not connected */
207         if (!p_r_tones
208          && p_state != PORT_STATE_CONNECT)
209                 return 0;
210
211         memset(&newparam, 0, sizeof(union parameter));
212         /* split, if exeeds data size */
213         while(len) {
214                 l = (len > (int)sizeof(newparam.traffic.data)) ? sizeof(newparam.traffic.data) : len;
215                 newparam.traffic.len = l;
216                 len -= l;
217                 memcpy(newparam.traffic.data, data, l);
218                 data += l;
219                 admin_message_from_lcr(p_r_remote_id, p_r_ref, MESSAGE_TRAFFIC, &newparam);
220         }
221
222         return 0;
223 }
224
225