d88ac7942d0b1ee44b3563b9c9b59a686b8091a7
[asterisk/asterisk.git] / addons / ooh323c / src / ooCmdChannel.c
1 /*
2  * Copyright (C) 2004-2005 by Objective Systems, Inc.
3  *
4  * This software is furnished under an open source license and may be 
5  * used and copied only in accordance with the terms of this license. 
6  * The text of the license may generally be found in the root 
7  * directory of this installation in the COPYING file.  It 
8  * can also be viewed online at the following URL:
9  *
10  *   http://www.obj-sys.com/open/license.html
11  *
12  * Any redistributions of this file including modified versions must 
13  * maintain this copyright notice.
14  *
15  *****************************************************************************/
16
17 #include "asterisk.h"
18 #include "asterisk/lock.h"
19 #include "ooStackCmds.h"
20 #include "ootrace.h"
21 #include "ooq931.h"
22 #include "ooh245.h"
23 #include "ooh323ep.h"
24 #include "oochannels.h"
25 #include "ooCalls.h"
26 #include "ooCmdChannel.h"
27
28
29 /** Global endpoint structure */
30 extern OOH323EndPoint gH323ep;
31
32 OOSOCKET gCmdChan = 0;
33 ast_mutex_t gCmdChanLock;
34
35 int ooCreateCmdConnection()
36 {
37    int ret = 0;
38    int thePipe[2];
39
40    if ((ret = pipe(thePipe)) == -1) {
41       return OO_FAILED;
42    }
43    ast_mutex_init(&gCmdChanLock);
44
45    gH323ep.cmdSock = dup(thePipe[0]);
46    close(thePipe[0]);
47    gCmdChan = dup(thePipe[1]);
48    close(thePipe[1]);
49    return OO_OK;
50 }
51
52 int ooCreateCallCmdConnection(OOH323CallData* call)
53 {
54    int ret = 0;
55    int thePipe[2];
56
57     OOTRACEINFO2("INFO: create cmd connect for call: %lx\n", call);
58
59    call->CmdChanLock = malloc(sizeof(ast_mutex_t));
60    ast_mutex_init(call->CmdChanLock);
61
62
63    if ((ret = socketpair(PF_LOCAL, SOCK_STREAM, 0, thePipe)) == -1) {
64       ast_mutex_destroy(call->CmdChanLock);
65       free(call->CmdChanLock);
66       call->CmdChanLock = NULL;
67       return OO_FAILED;
68    }
69    ast_mutex_lock(call->CmdChanLock);
70    call->cmdSock = thePipe[0];
71    call->CmdChan = thePipe[1];
72    ast_mutex_unlock(call->CmdChanLock);
73    return OO_OK;
74 }
75
76
77 int ooCloseCmdConnection()
78 {
79    close(gH323ep.cmdSock);
80    gH323ep.cmdSock = 0;
81    close(gCmdChan);
82    gCmdChan = 0;
83    ast_mutex_destroy(&gCmdChanLock);
84
85    return OO_OK;
86 }
87 int ooCloseCallCmdConnection(OOH323CallData* call)
88 {
89    ast_mutex_lock(call->CmdChanLock);
90    close(call->cmdSock);
91    call->cmdSock = 0;
92    close(call->CmdChan);
93    call->CmdChan = 0;
94    ast_mutex_unlock(call->CmdChanLock);
95    ast_mutex_destroy(call->CmdChanLock);
96    free(call->CmdChanLock);
97    call->CmdChanLock = NULL;
98
99    return OO_OK;
100 }
101
102 int ooWriteStackCommand(OOStackCommand *cmd)
103 {
104
105         ast_mutex_lock(&gCmdChanLock);
106         if (write(gCmdChan, (char*)cmd, sizeof(OOStackCommand)) == -1) {
107                 ast_mutex_unlock(&gCmdChanLock);
108                 return OO_FAILED;
109         }
110         ast_mutex_unlock(&gCmdChanLock);
111    
112         return OO_OK;
113 }
114 int ooWriteCallStackCommand(OOH323CallData* call, OOStackCommand *cmd)
115 {
116         unsigned char buffer[MAXMSGLEN];
117         unsigned char* bPoint;
118
119         memcpy(buffer, cmd,  sizeof(OOStackCommand));
120         bPoint = buffer +  sizeof(OOStackCommand);
121         if (cmd->param1 && cmd->plen1 > 0) {
122                 if (bPoint + cmd->plen1 >= buffer + MAXMSGLEN)
123                         return OO_FAILED;
124                 memcpy(bPoint, cmd->param1, cmd->plen1);
125                 bPoint += cmd->plen1;
126         }
127         if (cmd->param2 && cmd->plen2 > 0) {
128                 if (bPoint + cmd->plen2 >= buffer + MAXMSGLEN)
129                         return OO_FAILED;
130                 memcpy(bPoint, cmd->param2, cmd->plen2);
131                 bPoint += cmd->plen2;
132         }
133         if (cmd->param3 && cmd->plen3 > 0) {
134                 if (bPoint + cmd->plen3 >= buffer + MAXMSGLEN)
135                         return OO_FAILED;
136                 memcpy(bPoint, cmd->param3, cmd->plen3);
137                 bPoint += cmd->plen3;
138         }
139
140         ast_mutex_lock(call->CmdChanLock);
141         if (write(call->CmdChan, buffer, bPoint - buffer) == -1) {
142                 ast_mutex_unlock(call->CmdChanLock);
143                 return OO_FAILED;
144         }
145         ast_mutex_unlock(call->CmdChanLock);
146    
147         return OO_OK;
148 }
149
150
151 int ooReadAndProcessStackCommand()
152 {
153    OOH323CallData *pCall = NULL;   
154    unsigned char buffer[MAXMSGLEN];
155    int i, recvLen = 0;
156    OOStackCommand cmd;
157    memset(&cmd, 0, sizeof(OOStackCommand));
158    ast_mutex_lock(&gCmdChanLock);
159    recvLen = read(gH323ep.cmdSock, buffer, MAXMSGLEN);
160    ast_mutex_unlock(&gCmdChanLock);
161    if(recvLen <= 0)
162    {
163       OOTRACEERR1("Error:Failed to read CMD message\n");
164       return OO_FAILED;
165    }
166
167    for(i=0; (int)(i+sizeof(OOStackCommand)) <= recvLen; i += sizeof(OOStackCommand))
168    {
169       memcpy(&cmd, buffer+i, sizeof(OOStackCommand));
170
171       if(cmd.type == OO_CMD_NOOP)
172          continue;
173
174       if(gH323ep.gkClient && gH323ep.gkClient->state != GkClientRegistered)
175       {
176          OOTRACEINFO1("Ignoring stack command as Gk Client is not registered"
177                       " yet\n");
178       }
179       else {
180          switch(cmd.type) {
181             case OO_CMD_MAKECALL: 
182                OOTRACEINFO2("Processing MakeCall command %s\n", 
183                                     (char*)cmd.param2);
184  
185                ooH323NewCall ((char*)cmd.param2);
186                break;
187
188             case OO_CMD_MANUALPROGRESS:
189                 pCall = ooFindCallByToken((char*)cmd.param1);
190                 if(!pCall) {
191                    OOTRACEINFO2("Call \"%s\" does not exist\n",
192                                 (char*)cmd.param1);
193                    OOTRACEINFO1("Call migth be cleared/closed\n");
194                 }
195                 else {
196                      ooSendProgress(ooFindCallByToken((char*)cmd.param1));
197                 }
198                break;
199
200             case OO_CMD_MANUALRINGBACK:
201                if(OO_TESTFLAG(gH323ep.flags, OO_M_MANUALRINGBACK))
202                {
203                   pCall = ooFindCallByToken((char*)cmd.param1);
204                   if(!pCall) {
205                      OOTRACEINFO2("Call \"%s\" does not exist\n",
206                                   (char*)cmd.param1);
207                      OOTRACEINFO1("Call migth be cleared/closed\n");
208                   }
209                   else {
210                      ooSendAlerting(ooFindCallByToken((char*)cmd.param1));
211                      if(OO_TESTFLAG(gH323ep.flags, OO_M_AUTOANSWER)) {
212                         ooSendConnect(ooFindCallByToken((char*)cmd.param1));
213                      }
214                   }
215                }
216                break;
217  
218             case OO_CMD_ANSCALL:
219                pCall = ooFindCallByToken((char*)cmd.param1);
220                if(!pCall) {
221                   OOTRACEINFO2("Call \"%s\" does not exist\n",
222                                (char*)cmd.param1);
223                   OOTRACEINFO1("Call might be cleared/closed\n");
224                }
225                else {
226                   OOTRACEINFO2("Processing Answer Call command for %s\n",
227                                (char*)cmd.param1);
228                   ooSendConnect(pCall);
229                }
230                break;
231
232             case OO_CMD_FWDCALL:
233                OOTRACEINFO3("Forwarding call %s to %s\n", (char*)cmd.param1,
234                                                           (char*)cmd.param2);
235                ooH323ForwardCall((char*)cmd.param1, (char*)cmd.param2);
236                break;
237
238             case OO_CMD_HANGCALL: 
239                OOTRACEINFO3("Processing Hang call command %s with q931 cause %d\n", 
240                              (char*)cmd.param1, *(int *) cmd.param3);
241                ooH323HangCall((char*)cmd.param1, 
242                               *(OOCallClearReason*)cmd.param2, *(int *) cmd.param3);
243                break;
244           
245             case OO_CMD_SENDDIGIT:
246                pCall = ooFindCallByToken((char*)cmd.param1);
247                if(!pCall) {
248                   OOTRACEERR2("ERROR:Invalid calltoken %s\n",
249                               (char*)cmd.param1);
250                   break;
251                }
252                if(pCall->jointDtmfMode & OO_CAP_DTMF_H245_alphanumeric) {
253                   ooSendH245UserInputIndication_alphanumeric(
254                      pCall, (const char*)cmd.param2);
255                }
256                else if(pCall->jointDtmfMode & OO_CAP_DTMF_H245_signal) {
257                   ooSendH245UserInputIndication_signal(
258                      pCall, (const char*)cmd.param2);
259                }
260                else {
261                   ooQ931SendDTMFAsKeyPadIE(pCall, (const char*)cmd.param2);
262                }
263
264                break;
265
266             case OO_CMD_STOPMONITOR: 
267                OOTRACEINFO1("Processing StopMonitor command\n");
268                ooStopMonitorCalls();
269                break;
270
271             default: OOTRACEERR1("ERROR:Unknown command\n");
272          }
273       }
274       if(cmd.param1) free(cmd.param1);
275       if(cmd.param2) free(cmd.param2);
276       if(cmd.param3) free(cmd.param3);
277    }
278
279
280    return OO_OK;
281 }
282 int ooReadAndProcessCallStackCommand(OOH323CallData* call)
283 {
284    unsigned char buffer[MAXMSGLEN];
285    unsigned char *bPoint;
286    int recvLen = 0;
287    OOStackCommand cmd;
288    memset(&cmd, 0, sizeof(OOStackCommand));
289    if (call->CmdChanLock) {
290     ast_mutex_lock(call->CmdChanLock);
291     recvLen = read(call->cmdSock, buffer, MAXMSGLEN);
292     ast_mutex_unlock(call->CmdChanLock);
293    } else {
294     recvLen = read(call->cmdSock, buffer, MAXMSGLEN);
295    }
296    if(recvLen <= 0)
297    {
298       OOTRACEERR1("Error:Failed to read CMD message\n");
299       return OO_FAILED;
300    }
301
302    bPoint = buffer;
303    while (bPoint  < buffer + recvLen - sizeof(OOStackCommand)) {
304
305       memcpy(&cmd, bPoint, sizeof(OOStackCommand));
306       bPoint +=  sizeof(OOStackCommand);
307
308       if (cmd.plen1 > 0) {
309         cmd.param1 = malloc(cmd.plen1 + 1);
310         if (!cmd.param1) 
311                 return OO_FAILED;
312         memset(cmd.param1, 0, cmd.plen1 + 1);
313         memcpy(cmd.param1, bPoint, cmd.plen1);
314         bPoint += cmd.plen1;
315       }
316
317       if (cmd.plen2 > 0) {
318         cmd.param2 = malloc(cmd.plen2 + 1);
319         if (!cmd.param2) 
320                 return OO_FAILED;
321         memset(cmd.param2, 0, cmd.plen2 + 1);
322         memcpy(cmd.param2, bPoint, cmd.plen2);
323         bPoint += cmd.plen2;
324       }
325
326       if (cmd.plen3 > 0) {
327         cmd.param3 = malloc(cmd.plen3 + 1);
328         if (!cmd.param3) 
329                 return OO_FAILED;
330         memset(cmd.param3, 0, cmd.plen3 + 1);
331         memcpy(cmd.param3, bPoint, cmd.plen3);
332         bPoint += cmd.plen3;
333       }
334
335       if(cmd.type == OO_CMD_NOOP)
336          continue;
337
338       if(gH323ep.gkClient && gH323ep.gkClient->state != GkClientRegistered)
339       {
340          OOTRACEINFO1("Ignoring stack command as Gk Client is not registered"
341                       " yet\n");
342       }
343       else {
344          switch(cmd.type) {
345             case OO_CMD_MAKECALL: 
346                OOTRACEINFO2("Processing MakeCall command %s\n", 
347                                     (char*)cmd.param2);
348  
349                ooH323MakeCall ((char*)cmd.param1, (char*)cmd.param2, 
350                                (ooCallOptions*)cmd.param3);
351                break;
352
353             case OO_CMD_MANUALPROGRESS:
354                ooSendProgress(call);
355                break;
356
357             case OO_CMD_MANUALRINGBACK:
358                if(OO_TESTFLAG(gH323ep.flags, OO_M_MANUALRINGBACK))
359                {
360                  ooSendAlerting(call);
361                  if(OO_TESTFLAG(gH323ep.flags, OO_M_AUTOANSWER)) {
362                    ooSendConnect(call);
363                  }
364                }
365                break;
366  
367             case OO_CMD_ANSCALL:
368                   ooSendConnect(call);
369                break;
370
371             case OO_CMD_FWDCALL:
372                OOTRACEINFO3("Forwarding call %s to %s\n", (char*)cmd.param1,
373                                                           (char*)cmd.param2);
374                ooH323ForwardCall((char*)cmd.param1, (char*)cmd.param2);
375                break;
376
377             case OO_CMD_HANGCALL: 
378                OOTRACEINFO2("Processing Hang call command %s with q931 cause %d\n", 
379                              (char*)cmd.param1);
380                ooH323HangCall((char*)cmd.param1, 
381                               *(OOCallClearReason*)cmd.param2, *(int *) cmd.param3);
382                break;
383           
384             case OO_CMD_SENDDIGIT:
385                if(call->jointDtmfMode & OO_CAP_DTMF_H245_alphanumeric) {
386                   ooSendH245UserInputIndication_alphanumeric(
387                      call, (const char*)cmd.param2);
388                }
389                else if(call->jointDtmfMode & OO_CAP_DTMF_H245_signal) {
390                   ooSendH245UserInputIndication_signal(
391                      call, (const char*)cmd.param2);
392                }
393                else {
394                   ooQ931SendDTMFAsKeyPadIE(call, (const char*)cmd.param2);
395                }
396
397                break;
398
399             case OO_CMD_REQMODE:
400                OOTRACEINFO3("Processing RequestMode command %s, requested mode is %d\n",
401                                 (char *)cmd.param1, *(int *)cmd.param2);
402                ooSendRequestMode(call, *(int *)cmd.param2);
403                break;
404
405             case OO_CMD_SETANI:
406                 OOTRACEINFO3("Processing SetANI command %s, ani is %s\n",
407                                 (char *)cmd.param1, (char *)cmd.param2);
408                 if(cmd.param2) {
409                         strncpy(call->ourCallerId, cmd.param2, sizeof(call->ourCallerId)-1);
410                         call->ourCallerId[sizeof(call->ourCallerId)-1] = '\0';
411                 }
412                 break;
413
414             default: OOTRACEERR1("ERROR:Unknown command\n");
415          }
416       }
417       if(cmd.param1) free(cmd.param1);
418       if(cmd.param2) free(cmd.param2);
419       if(cmd.param3) free(cmd.param3);
420    }
421
422
423    return OO_OK;
424 }
425