Merged revisions 317837 via svnmerge from
[asterisk/asterisk.git] / addons / ooh323c / src / ooLogChan.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
20 #include "ooCalls.h"
21 #include "ooh323ep.h"
22
23 /** Global endpoint structure */
24 extern OOH323EndPoint gH323ep;
25
26 OOLogicalChannel* ooAddNewLogicalChannel(OOH323CallData *call, int channelNo, 
27                                          int sessionID, char *dir, 
28                                          ooH323EpCapability *epCap)
29 {
30    OOLogicalChannel *pNewChannel=NULL, *pChannel=NULL;
31    OOMediaInfo *pMediaInfo = NULL;
32    OOTRACEDBGC5("Adding new media channel for cap %d dir %s (%s, %s)\n",
33                epCap->cap, dir, call->callType, call->callToken);
34    /* Create a new logical channel entry */
35    pNewChannel = (OOLogicalChannel*)memAlloc(call->pctxt, 
36                                                      sizeof(OOLogicalChannel));
37    if(!pNewChannel)
38    {
39       OOTRACEERR3("ERROR:Memory - ooAddNewLogicalChannel - pNewChannel "
40                   "(%s, %s)\n", call->callType, call->callToken);
41       return NULL;
42    }
43    
44    memset(pNewChannel, 0, sizeof(OOLogicalChannel));
45    pNewChannel->channelNo = channelNo;
46    pNewChannel->sessionID = sessionID;
47    pNewChannel->state = OO_LOGICALCHAN_IDLE;
48    pNewChannel->type = epCap->capType;
49    /*   strcpy(pNewChannel->type, type);*/
50    strcpy(pNewChannel->dir, dir);
51
52    pNewChannel->chanCap = epCap;
53    OOTRACEDBGC4("Adding new channel with cap %d (%s, %s)\n", epCap->cap,
54                 call->callType, call->callToken); 
55    /* As per standards, media control port should be same for all 
56       proposed channels with same session ID. However, most applications
57       use same media port for transmit and receive of audio streams. Infact,
58       testing of OpenH323 based asterisk assumed that same ports are used. 
59       Hence we first search for existing media ports for same session and use 
60       them. This should take care of all cases.
61    */
62    if(call->mediaInfo)
63    {
64       pMediaInfo = call->mediaInfo;
65       while(pMediaInfo)
66       {
67          if(!strcmp(pMediaInfo->dir, dir) &&
68             (pMediaInfo->cap == epCap->cap))
69          {
70             break;
71          }
72          pMediaInfo = pMediaInfo->next;
73       }
74    }
75     
76    if(pMediaInfo)
77    {
78       OOTRACEDBGC3("Using configured media info (%s, %s)\n", call->callType,
79                    call->callToken);
80       pNewChannel->localRtpPort = pMediaInfo->lMediaPort;
81       pNewChannel->localRtcpPort = pMediaInfo->lMediaCntrlPort;
82       /* If user application has not specified a specific ip and is using 
83          multihomed mode, substitute appropriate ip.
84       */
85       if(!strcmp(pMediaInfo->lMediaIP, "0.0.0.0") || !strcmp(pMediaInfo->lMediaIP, "::"))
86          strcpy(pNewChannel->localIP, call->localIP);
87       else
88          strcpy(pNewChannel->localIP, pMediaInfo->lMediaIP);
89    }
90    else{
91       OOTRACEDBGC3("Using default media info (%s, %s)\n", call->callType,
92                    call->callToken);
93       pNewChannel->localRtpPort = ooGetNextPort (OORTP);
94
95       /* Ensures that RTP port is an even one */
96       if((pNewChannel->localRtpPort & 1) == 1)
97         pNewChannel->localRtpPort = ooGetNextPort (OORTP);
98
99       pNewChannel->localRtcpPort = ooGetNextPort (OORTP);
100       strcpy(pNewChannel->localIP, call->localIP);
101    }
102    
103    /* Add new channel to the list */
104    pNewChannel->next = NULL;
105    if(!call->logicalChans) {
106       call->logicalChans = pNewChannel;
107    }
108    else{
109       pChannel = call->logicalChans;
110       while(pChannel->next)  pChannel = pChannel->next;
111       pChannel->next = pNewChannel;
112    }
113    
114    /* increment logical channels */
115    call->noOfLogicalChannels++;
116    OOTRACEINFO3("Created new logical channel entry (%s, %s)\n", call->callType,
117                 call->callToken);
118    return pNewChannel;
119 }
120
121 OOLogicalChannel* ooFindLogicalChannelByLogicalChannelNo(OOH323CallData *call,
122                                                          int ChannelNo)
123 {
124    OOLogicalChannel *pLogicalChannel=NULL;
125    if(!call->logicalChans)
126    {
127       OOTRACEWARN3("ERROR: No Open LogicalChannels - Failed "
128                   "FindLogicalChannelByChannelNo (%s, %s\n", call->callType,
129                    call->callToken);
130       return NULL;
131    }
132    pLogicalChannel = call->logicalChans;
133    while(pLogicalChannel)
134    {
135       if(pLogicalChannel->channelNo == ChannelNo)
136          break;
137       else
138          pLogicalChannel = pLogicalChannel->next;
139    }
140
141    return pLogicalChannel;
142 }
143
144 OOLogicalChannel * ooFindLogicalChannelByOLC(OOH323CallData *call, 
145                                H245OpenLogicalChannel *olc)
146 {
147    H245DataType * psDataType=NULL;
148    H245H2250LogicalChannelParameters * pslcp=NULL;
149    OOTRACEDBGC4("ooFindLogicalChannel by olc %d (%s, %s)\n", 
150             olc->forwardLogicalChannelNumber, call->callType, call->callToken);
151    if(olc->m.reverseLogicalChannelParametersPresent)
152    {
153       OOTRACEDBGC3("Finding receive channel (%s,%s)\n", call->callType, 
154                                                        call->callToken);
155       psDataType = &olc->reverseLogicalChannelParameters.dataType;
156       /* Only H2250LogicalChannelParameters are supported */
157       if(olc->reverseLogicalChannelParameters.multiplexParameters.t !=
158          T_H245OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters){
159          OOTRACEERR4("Error:Invalid olc %d received (%s, %s)\n", 
160            olc->forwardLogicalChannelNumber, call->callType, call->callToken);
161          return NULL;
162       }
163       pslcp = olc->reverseLogicalChannelParameters.multiplexParameters.u.h2250LogicalChannelParameters;
164
165       return ooFindLogicalChannel(call, pslcp->sessionID, "receive", psDataType);
166    }
167    else{
168       OOTRACEDBGC3("Finding transmit channel (%s, %s)\n", call->callType, 
169                                                            call->callToken);
170       psDataType = &olc->forwardLogicalChannelParameters.dataType;
171       /* Only H2250LogicalChannelParameters are supported */
172       if(olc->forwardLogicalChannelParameters.multiplexParameters.t != 
173          T_H245OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)
174       {
175          OOTRACEERR4("Error:Invalid olc %d received (%s, %s)\n", 
176            olc->forwardLogicalChannelNumber, call->callType, call->callToken);
177          return NULL;
178       }
179       pslcp = olc->forwardLogicalChannelParameters.multiplexParameters.u.h2250LogicalChannelParameters;
180       return ooFindLogicalChannel(call, pslcp->sessionID, "transmit", psDataType);
181    }
182 }
183
184 OOLogicalChannel * ooFindLogicalChannel(OOH323CallData *call, int sessionID, 
185                                         char *dir, H245DataType * dataType)
186 {
187    OOLogicalChannel * pChannel = NULL;
188    pChannel = call->logicalChans;
189    while(pChannel)
190    {
191       OOTRACEDBGC3("ooFindLogicalChannel, checking channel: %d:%s\n",
192                     pChannel->sessionID, pChannel->dir);
193       if(pChannel->sessionID == sessionID || pChannel->sessionID == 0)
194       {
195          if(!strcmp(pChannel->dir, dir))
196          {
197             OOTRACEDBGC3("ooFindLogicalChannel, comparing channel: %d:%s\n",
198                           pChannel->channelNo, pChannel->dir);
199             if(!strcmp(dir, "receive"))
200             {
201                if(ooCapabilityCheckCompatibility(call, pChannel->chanCap,
202                                                  dataType, OORX)) {
203                   return pChannel;
204                }
205             }
206             else if(!strcmp(dir, "transmit"))
207             {
208                if(ooCapabilityCheckCompatibility(call, pChannel->chanCap,
209                                                  dataType, OOTX)) {
210                   return pChannel;
211                }
212             }
213          }
214       }
215       pChannel = pChannel->next;
216    }
217    return NULL;
218 }
219
220 /* This function is used to get a logical channel with a particular session ID */
221 OOLogicalChannel* ooGetLogicalChannel
222    (OOH323CallData *call, int sessionID, char *dir)
223 {
224    OOLogicalChannel * pChannel = NULL;
225    pChannel = call->logicalChans;
226    while(pChannel)
227    {
228       if(pChannel->sessionID == sessionID && !strcmp(pChannel->dir, dir))
229          return pChannel;
230       else
231          pChannel = pChannel->next;
232    }
233    return NULL;
234 }
235
236 /* function is to get channel with particular direction */
237
238 OOLogicalChannel* ooGetTransmitLogicalChannel
239    (OOH323CallData *call)
240 {
241    OOLogicalChannel * pChannel = NULL;
242    pChannel = call->logicalChans;
243    while(pChannel)
244    {
245       OOTRACEINFO6("Listing logical channel %d cap %d state %d for (%s, %s)\n",
246                 pChannel->channelNo, pChannel->chanCap->cap, pChannel->state, 
247                 call->callType, call->callToken);
248       if(!strcmp(pChannel->dir, "transmit") && pChannel->state != OO_LOGICALCHAN_IDLE &&
249                                                pChannel->state != OO_LOGICALCHAN_PROPOSEDFS)
250          return pChannel;
251       else
252          pChannel = pChannel->next;
253    }
254    return NULL;
255 }
256
257 int ooClearAllLogicalChannels(OOH323CallData *call)
258 {
259    OOLogicalChannel * temp = NULL, *prev = NULL;
260
261    OOTRACEINFO3("Clearing all logical channels (%s, %s)\n", call->callType,
262                  call->callToken);
263    
264    temp = call->logicalChans;
265    while(temp)
266    {
267       prev = temp;
268       temp = temp->next;
269       ooClearLogicalChannel(call, prev->channelNo);/* TODO: efficiency - This causes re-search 
270                                                       of of logical channel in the list. Can be
271                                                       easily improved.*/
272    }
273    call->logicalChans = NULL;
274    return OO_OK;
275 }
276
277 int ooClearLogicalChannel(OOH323CallData *call, int channelNo)
278 {
279
280    OOLogicalChannel *pLogicalChannel = NULL;
281    ooH323EpCapability *epCap=NULL;
282
283    OOTRACEDBGC4("Clearing logical channel number %d. (%s, %s)\n", channelNo,
284                  call->callType, call->callToken);
285
286    pLogicalChannel = ooFindLogicalChannelByLogicalChannelNo(call,channelNo);
287    if(!pLogicalChannel)
288    {
289       OOTRACEWARN4("Logical Channel %d doesn't exist, in clearLogicalChannel."
290                    " (%s, %s)\n",
291                   channelNo, call->callType, call->callToken);
292       return OO_OK;
293    }
294
295    epCap = (ooH323EpCapability*) pLogicalChannel->chanCap;
296    if(!strcmp(pLogicalChannel->dir, "receive"))
297    {
298       if(epCap->stopReceiveChannel)
299       {
300          epCap->stopReceiveChannel(call, pLogicalChannel);
301          OOTRACEINFO4("Stopped Receive channel %d (%s, %s)\n", 
302                                  channelNo, call->callType, call->callToken);
303       }
304       else{
305          OOTRACEERR4("ERROR:No callback registered for stopReceiveChannel %d "
306                      "(%s, %s)\n", channelNo, call->callType, call->callToken);
307       }
308    }
309    else
310    {
311       if(pLogicalChannel->state == OO_LOGICALCHAN_ESTABLISHED)
312       {
313          if(epCap->stopTransmitChannel)
314          {
315             epCap->stopTransmitChannel(call, pLogicalChannel);
316             OOTRACEINFO4("Stopped Transmit channel %d (%s, %s)\n", 
317                           channelNo, call->callType, call->callToken);
318          }
319          else{
320             OOTRACEERR4("ERROR:No callback registered for stopTransmitChannel"
321                         " %d (%s, %s)\n", channelNo, call->callType, 
322                         call->callToken);
323          }
324       }
325    }
326    ooRemoveLogicalChannel(call, channelNo);/* TODO: efficiency - This causes re-search of
327                                                     of logical channel in the list. Can be
328                                                     easily improved.*/
329    return OO_OK;
330 }
331
332 int ooRemoveLogicalChannel(OOH323CallData *call, int ChannelNo)
333 {
334    OOLogicalChannel * temp = NULL, *prev=NULL; 
335    if(!call->logicalChans)
336    {
337       OOTRACEERR4("ERROR:Remove Logical Channel - Channel %d not found "
338                   "Empty channel List(%s, %s)\n", ChannelNo, call->callType, 
339                   call->callToken);
340       return OO_FAILED;
341    }
342
343    temp = call->logicalChans;
344    while(temp)
345    {
346       if(temp->channelNo == ChannelNo)
347       {
348          if(!prev)   call->logicalChans = temp->next;
349          else   prev->next = temp->next;
350          memFreePtr(call->pctxt, temp->chanCap);
351          memFreePtr(call->pctxt, temp);
352          OOTRACEDBGC4("Removed logical channel %d (%s, %s)\n", ChannelNo,
353                        call->callType, call->callToken);
354          call->noOfLogicalChannels--;
355          return OO_OK;
356       }
357       prev = temp;
358       temp = temp->next;
359    }
360    
361    OOTRACEERR4("ERROR:Remove Logical Channel - Channel %d not found "
362                   "(%s, %s)\n", ChannelNo, call->callType, call->callToken);
363    return OO_FAILED;
364 }
365
366 /* 
367 Change the state of the channel as established and close all other 
368 channels with same session IDs. This is useful for handling fastStart, 
369 as the endpoint can open multiple logical channels for same sessionID.
370 Once the remote endpoint confirms it's selection, all other channels for 
371 the same sessionID must be closed.
372 */
373 int ooOnLogicalChannelEstablished
374    (OOH323CallData *call, OOLogicalChannel * pChannel)
375 {
376    OOLogicalChannel * temp = NULL, *prev=NULL; 
377    OOTRACEDBGC3("In ooOnLogicalChannelEstablished (%s, %s)\n",
378                 call->callType, call->callToken);
379    pChannel->state = OO_LOGICALCHAN_ESTABLISHED;
380    temp = call->logicalChans;
381    while(temp)
382    {
383       if(temp->channelNo != pChannel->channelNo &&
384          temp->sessionID == pChannel->sessionID &&
385          !strcmp(temp->dir, pChannel->dir)        )
386       {
387          prev = temp;
388          temp = temp->next;
389          ooClearLogicalChannel(call, prev->channelNo);
390       }
391       else
392          temp = temp->next;
393    }
394    return OO_OK;
395 }
396