~ubuntu-branches/debian/squeeze/asterisk-chan-capi/squeeze

« back to all changes in this revision

Viewing changes to app_capiECT.c

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings
  • Date: 2007-03-07 01:58:53 UTC
  • mfrom: (3.1.3 feisty)
  • Revision ID: james.westby@ubuntu.com-20070307015853-yw0ov095k4fx2rza
Tags: 0.7.1-1.1
* Non-maintainer upload
* Protect calls to capi_cmsg2str and use of its buffer with a mutex.
  (Closes: #411293)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * (CAPI*)
3
 
 *
4
 
 * An implementation of Common ISDN API 2.0 for Asterisk
5
 
 *
6
 
 * ECT transfer the holded call 
7
 
 *
8
 
 * Copyright (C) 2002, Junghanns.NET GmbH
9
 
 *
10
 
 * Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
11
 
 *
12
 
 * This program is free software and may be modified and 
13
 
 * distributed under the terms of the GNU Public License.
14
 
 */
15
 
 
16
 
#include <asterisk/file.h>
17
 
#include <asterisk/logger.h>
18
 
#include <asterisk/channel.h>
19
 
#include <asterisk/channel_pvt.h>
20
 
#include <asterisk/pbx.h>
21
 
#include <asterisk/module.h>
22
 
#include <asterisk/say.h>
23
 
#include <stdlib.h>
24
 
#include <unistd.h>
25
 
#include <string.h>
26
 
#include <stdlib.h>
27
 
 
28
 
#include <pthread.h>
29
 
#include <linux/capi.h>
30
 
#include <capi20.h>
31
 
#include "chan_capi_pvt.h"
32
 
#include "chan_capi_app.h"
33
 
 
34
 
 
35
 
static char *tdesc = "(CAPI*) ECT";
36
 
static char *app = "capiECT";
37
 
static char *synopsis = "transfer the call that is on hold";
38
 
 
39
 
STANDARD_LOCAL_USER;
40
 
 
41
 
LOCAL_USER_DECL;
42
 
 
43
 
 
44
 
static int capiECT_exec(struct ast_channel *chan, void *data)
45
 
{
46
 
    struct ast_capi_pvt *i = chan->pvt->pvt;
47
 
    MESSAGE_EXCHANGE_ERROR Info;
48
 
    _cmsg       CMSG;
49
 
    char        fac[8];
50
 
    int res=0;
51
 
    struct localuser *u;
52
 
    char *ecodes = "*#";
53
 
 
54
 
    if (!data) {
55
 
        ast_log(LOG_WARNING, "ECT requires an argument (destination phone number)\n");
56
 
        return -1;
57
 
    }
58
 
    LOCAL_USER_ADD(u);
59
 
    /* Do our thing here */
60
 
    if (i->onholdPLCI <= 0) {
61
 
        ast_log(LOG_WARNING, "no call on hold that could be transfered\n");
62
 
        return -1;
63
 
    }
64
 
 
65
 
    ast_log(LOG_NOTICE,"ECT to %s\n",(char *)data);
66
 
    capi_call(chan,data,0);
67
 
 
68
 
    while ((i->state != CAPI_STATE_BCONNECTED) && (i->onholdPLCI != 0)) {
69
 
        usleep(10000);
70
 
    }
71
 
 
72
 
 
73
 
    if (i->state == CAPI_STATE_BCONNECTED) {
74
 
        ast_log(LOG_NOTICE,"call was answered\n");
75
 
 
76
 
        capi_detect_dtmf(chan,1);
77
 
 
78
 
        // put the stuff to play announcement message here --->   <-----
79
 
        res = ast_say_digit_str(chan,i->cid,ecodes,chan->language);
80
 
        if ( res == '#') {
81
 
            ast_log(LOG_NOTICE,"res = %d\n",res);
82
 
            // user pressed #, hangup
83
 
                // first the holded user
84
 
//              ast_exec("capiRETRIEVE",chan);
85
 
 
86
 
                DISCONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
87
 
                DISCONNECT_REQ_PLCI(&CMSG) = i->onholdPLCI;
88
 
 
89
 
                if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
90
 
                    ast_log(LOG_NOTICE, "error sending DISCONNECT_REQ PLCI=%#x\n",i->onholdPLCI);
91
 
                } else {
92
 
                    ast_log(LOG_NOTICE, "sent DISCONNECT_REQ PLCI=%#x\n",i->onholdPLCI);
93
 
                }
94
 
                
95
 
                // then the destination
96
 
 
97
 
                DISCONNECT_B3_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
98
 
                DISCONNECT_B3_REQ_NCCI(&CMSG) = i->NCCI;
99
 
 
100
 
                if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
101
 
                    ast_log(LOG_NOTICE, "error sending DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
102
 
                } else {
103
 
                    ast_log(LOG_NOTICE, "sent DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
104
 
                }
105
 
 
106
 
                // wait for the B3 layer to go down
107
 
                while (i->state != CAPI_STATE_CONNECTED) {
108
 
                    usleep(10000);
109
 
                }
110
 
 
111
 
                DISCONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
112
 
                DISCONNECT_REQ_PLCI(&CMSG) = i->PLCI;
113
 
 
114
 
                if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
115
 
                    ast_log(LOG_NOTICE, "error sending DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
116
 
                } else {
117
 
                    ast_log(LOG_NOTICE, "sent DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
118
 
                }
119
 
                
120
 
                
121
 
                LOCAL_USER_REMOVE(u);
122
 
                return -1;
123
 
 
124
 
        } else {
125
 
            // now drop the bchannel
126
 
            DISCONNECT_B3_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
127
 
            DISCONNECT_B3_REQ_NCCI(&CMSG) = i->NCCI;
128
 
 
129
 
            if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
130
 
                ast_log(LOG_NOTICE, "error sending DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
131
 
            } else {
132
 
                ast_log(LOG_NOTICE, "sent DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
133
 
            }
134
 
 
135
 
            // wait for the B3 layer to go down
136
 
            while (i->state != CAPI_STATE_CONNECTED) {
137
 
                usleep(10000);
138
 
            } 
139
 
        }
140
 
    }
141
 
 
142
 
    // the caller onhold hungup or died away, drop the answered call
143
 
    if (i->onholdPLCI == 0) {
144
 
        DISCONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
145
 
        DISCONNECT_REQ_PLCI(&CMSG) = i->PLCI;
146
 
 
147
 
        if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
148
 
            ast_log(LOG_NOTICE, "error sending DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
149
 
        } else {
150
 
            ast_log(LOG_NOTICE, "sent DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
151
 
        }
152
 
        return -1;
153
 
    }
154
 
 
155
 
    ast_log(LOG_NOTICE,"onholdPLCI = %d\n",i->onholdPLCI);
156
 
 
157
 
 
158
 
    fac[0] = 7; // len
159
 
    fac[1] = 0x06; // ECT (function)
160
 
    fac[2] = 0x00;
161
 
    fac[3] = 4; //len   //sservice specific parameter , cstruct
162
 
    fac[4] = (i->onholdPLCI << 8 ) >> 8;
163
 
    fac[5] = i->onholdPLCI >> 8;
164
 
    fac[6] = 0;
165
 
    fac[7] = 0;
166
 
 
167
 
    FACILITY_REQ_HEADER(&CMSG,ast_capi_ApplID,ast_capi_MessageNumber++,0);
168
 
    FACILITY_REQ_CONTROLLER(&CMSG) = i->controller;
169
 
    FACILITY_REQ_PLCI(&CMSG) = i->onholdPLCI;
170
 
    FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 0x0003; // sservices
171
 
    FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = (char *)&fac;
172
 
 
173
 
    if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
174
 
        ast_log(LOG_ERROR,"Error sending FACILITY_REQ\n");
175
 
        return Info;
176
 
    } else {
177
 
        ast_log(LOG_NOTICE,"sent FACILITY_REQ PLCI = %#x (%#x %#x) onholdPLCI = %#x\n ",i->PLCI,fac[4],fac[5],i->onholdPLCI);
178
 
        ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(&CMSG));
179
 
    }
180
 
 
181
 
//    i->outgoing = -1; // incoming + outgoing, this is a magic channel :)
182
 
 
183
 
    LOCAL_USER_REMOVE(u);
184
 
    return res;
185
 
}
186
 
 
187
 
int unload_module(void)
188
 
{
189
 
        STANDARD_HANGUP_LOCALUSERS;
190
 
        return ast_unregister_application(app);
191
 
}
192
 
 
193
 
int load_module(void)
194
 
{
195
 
        return ast_register_application(app, capiECT_exec,synopsis,tdesc);
196
 
}
197
 
 
198
 
char *description(void)
199
 
{
200
 
        return tdesc;
201
 
}
202
 
 
203
 
int usecount(void)
204
 
{
205
 
        int res;
206
 
        STANDARD_USECOUNT(res);
207
 
        return res;
208
 
}
209
 
 
210
 
char *key()
211
 
{
212
 
        return ASTERISK_GPL_KEY;
213
 
}