Changeset 2156


Ignore:
Timestamp:
Jul 18, 2008 11:00:56 PM (16 years ago)
Author:
bennylp
Message:

Implemented ticket #192 for Python: Add callback to notify application about incoming SUBSCRIBE request, and add subscription state and termination reason in buddy info

Location:
pjproject/trunk/pjsip-apps/src/python
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip-apps/src/python/_pjsua.c

    r2119 r2156  
    341341} 
    342342 
     343/*  
     344 * cb_on_incoming_subscribe 
     345 */ 
     346static void cb_on_incoming_subscribe( pjsua_acc_id acc_id, 
     347                                      pjsua_srv_pres *srv_pres, 
     348                                      pjsua_buddy_id buddy_id, 
     349                                      const pj_str_t *from, 
     350                                      pjsip_rx_data *rdata, 
     351                                      pjsip_status_code *code, 
     352                                      pj_str_t *reason, 
     353                                      pjsua_msg_data *msg_data) 
     354{ 
     355    static char reason_buf[64]; 
     356 
     357    PJ_UNUSED_ARG(rdata); 
     358    PJ_UNUSED_ARG(msg_data); 
     359 
     360    if (PyCallable_Check(g_obj_callback->on_incoming_subscribe)) 
     361    { 
     362        PyObject *ret; 
     363 
     364        ENTER_PYTHON(); 
     365 
     366        ret = PyObject_CallFunctionObjArgs( 
     367            g_obj_callback->on_incoming_subscribe, 
     368            Py_BuildValue("i", acc_id), 
     369            Py_BuildValue("i", buddy_id), 
     370            PyString_FromStringAndSize(from->ptr, from->slen), 
     371            PyLong_FromLong((long)srv_pres), 
     372            NULL 
     373        ); 
     374 
     375        if (ret && PyTuple_Check(ret)) { 
     376            if (PyTuple_Size(ret) >= 1) 
     377                *code = (int)PyInt_AsLong(PyTuple_GetItem(ret, 0)); 
     378            if (PyTuple_Size(ret) >= 2) { 
     379                if (PyTuple_GetItem(ret, 1) != Py_None) { 
     380                    pj_str_t tmp; 
     381                    tmp = PyString_to_pj_str(PyTuple_GetItem(ret, 1)); 
     382                    reason->ptr = reason_buf; 
     383                    pj_strncpy(reason, &tmp, sizeof(reason_buf)); 
     384                } else { 
     385                } 
     386            } 
     387 
     388        } else if (ret) { 
     389            Py_XDECREF(ret); 
     390        } 
     391 
     392        LEAVE_PYTHON(); 
     393    } 
     394} 
    343395 
    344396/* 
     
    372424                        pjsip_rx_data *rdata, pjsua_acc_id acc_id) 
    373425{ 
     426    PJ_UNUSED_ARG(rdata); 
     427 
    374428    if (PyCallable_Check(g_obj_callback->on_pager)) 
    375429    { 
     
    912966        cfg_ua.cb.on_call_replaced = &cb_on_call_replaced; 
    913967        cfg_ua.cb.on_reg_state = &cb_on_reg_state; 
     968        cfg_ua.cb.on_incoming_subscribe = &cb_on_incoming_subscribe; 
    914969        cfg_ua.cb.on_buddy_state = &cb_on_buddy_state; 
    915970        cfg_ua.cb.on_pager2 = &cb_on_pager; 
     
    18791934} 
    18801935 
     1936 
     1937/* 
     1938 * py_pjsua_acc_pres_notify 
     1939 */ 
     1940static PyObject *py_pjsua_acc_pres_notify 
     1941(PyObject *pSelf, PyObject *pArgs) 
     1942{ 
     1943    static char reason_buf[64]; 
     1944    int acc_id, state; 
     1945    PyObject *arg_pres, *arg_msg_data; 
     1946    void *srv_pres; 
     1947    pjsua_msg_data msg_data; 
     1948    const char *arg_reason; 
     1949    pj_str_t reason; 
     1950    pj_bool_t with_body; 
     1951    pj_pool_t *pool = NULL; 
     1952    int status;  
     1953     
     1954    PJ_UNUSED_ARG(pSelf); 
     1955 
     1956    if (!PyArg_ParseTuple(pArgs, "iOisO", &acc_id, &arg_pres,  
     1957                          &state, &arg_reason, &arg_msg_data)) 
     1958    { 
     1959        return NULL; 
     1960    }    
     1961     
     1962    srv_pres = (void*) PyLong_AsLong(arg_pres); 
     1963    pjsua_msg_data_init(&msg_data); 
     1964    with_body = (state != PJSIP_EVSUB_STATE_TERMINATED); 
     1965 
     1966    if (arg_reason) { 
     1967        strncpy(reason_buf, arg_reason, sizeof(reason_buf)); 
     1968        reason.ptr = reason_buf; 
     1969        reason.slen = strlen(arg_reason); 
     1970    } else { 
     1971        reason = pj_str(""); 
     1972    } 
     1973 
     1974    if (arg_msg_data && arg_msg_data != Py_None) { 
     1975        PyObj_pjsua_msg_data *omd = (PyObj_pjsua_msg_data *)arg_msg_data; 
     1976        msg_data.content_type.ptr = PyString_AsString(omd->content_type); 
     1977        msg_data.content_type.slen = PyString_Size(omd->content_type); 
     1978        msg_data.msg_body.ptr = PyString_AsString(omd->msg_body); 
     1979        msg_data.msg_body.slen = PyString_Size(omd->msg_body); 
     1980        pool = pjsua_pool_create("pytmp", POOL_SIZE, POOL_SIZE); 
     1981        translate_hdr(pool, &msg_data.hdr_list, omd->hdr_list); 
     1982    } else if (arg_msg_data) { 
     1983        Py_XDECREF(arg_msg_data);     
     1984    } 
     1985 
     1986    status = pjsua_pres_notify(acc_id, (pjsua_srv_pres*)srv_pres, 
     1987                               (pjsip_evsub_state)state, NULL, 
     1988                               &reason, with_body, &msg_data); 
     1989     
     1990    if (pool) { 
     1991        pj_pool_release(pool); 
     1992    } 
     1993 
     1994    return Py_BuildValue("i", status); 
     1995} 
    18811996 
    18821997static char pjsua_acc_config_default_doc[] = 
     
    55435658    }, 
    55445659    { 
     5660        "acc_pres_notify", py_pjsua_acc_pres_notify, METH_VARARGS, 
     5661        "Accept or reject subscription request" 
     5662    }, 
     5663    { 
    55455664        "enum_accs", py_pjsua_enum_accs, METH_VARARGS, 
    55465665        pjsua_enum_accs_doc 
  • pjproject/trunk/pjsip-apps/src/python/_pjsua.h

    r2119 r2156  
    508508    PyObject * on_call_replaced; 
    509509    PyObject * on_reg_state; 
     510    PyObject * on_incoming_subscribe; 
    510511    PyObject * on_buddy_state; 
    511512    PyObject * on_pager; 
     
    530531    Py_XDECREF(self->on_call_replaced); 
    531532    Py_XDECREF(self->on_reg_state); 
     533    Py_XDECREF(self->on_incoming_subscribe); 
    532534    Py_XDECREF(self->on_buddy_state); 
    533535    Py_XDECREF(self->on_pager); 
     
    617619            return NULL; 
    618620        } 
     621        Py_INCREF(Py_None); 
     622        self->on_incoming_subscribe = Py_None; 
    619623        Py_INCREF(Py_None); 
    620624        self->on_buddy_state = Py_None; 
     
    718722        "Notify application when registration status has changed. Application " 
    719723        "may then query the account info to get the registration details." 
     724    }, 
     725    { 
     726        "on_incoming_subscribe", T_OBJECT_EX, 
     727        offsetof(PyObj_pjsua_callback, on_incoming_subscribe), 0, 
     728        "Notification when incoming SUBSCRIBE request is received." 
    720729    }, 
    721730    { 
     
    27692778    int          monitor_pres; 
    27702779    int          activity; 
     2780    int          sub_state; 
     2781    PyObject    *sub_term_reason; 
    27712782} PyObj_pjsua_buddy_info; 
    27722783 
     
    27822793    Py_XDECREF(self->contact); 
    27832794    Py_XDECREF(self->status_text); 
     2795    Py_XDECREF(self->sub_term_reason); 
    27842796     
    27852797    self->ob_type->tp_free((PyObject*)self); 
     
    28012813    obj->monitor_pres = info->monitor_pres; 
    28022814    obj->activity = info->rpid.activity; 
     2815    obj->sub_state = info->sub_state; 
     2816    Py_XDECREF(obj->sub_term_reason); 
     2817    obj->sub_term_reason = PyString_FromStringAndSize(info->sub_term_reason.ptr,  
     2818                                                      info->sub_term_reason.slen); 
    28032819} 
    28042820 
     
    28242840            Py_DECREF(self); 
    28252841            return NULL; 
    2826         }         
     2842        } 
    28272843        self->contact = PyString_FromString(""); 
    28282844        if (self->contact == NULL) { 
     
    28352851            return NULL; 
    28362852        } 
    2837          
     2853        self->sub_term_reason = PyString_FromString(""); 
    28382854    } 
    28392855    return (PyObject *)self; 
     
    28822898        offsetof(PyObj_pjsua_buddy_info, activity), 0, 
    28832899        "Activity type. " 
     2900    }, 
     2901    { 
     2902        "sub_state", T_INT,  
     2903        offsetof(PyObj_pjsua_buddy_info, sub_state), 0, 
     2904        "Subscription state." 
     2905    }, 
     2906    { 
     2907        "sub_term_reason", T_INT,  
     2908        offsetof(PyObj_pjsua_buddy_info, sub_term_reason), 0, 
     2909        "Subscription termination reason." 
    28842910    }, 
    28852911     
  • pjproject/trunk/pjsip-apps/src/python/pjsua.py

    r2122 r2156  
    148148    Member documentation: 
    149149 
    150     NONE        -- media is not available. 
     150    NULL        -- media is not available. 
    151151    ACTIVE      -- media is active. 
    152152    LOCAL_HOLD  -- media is put on-hold by local party. 
     
    154154    ERROR       -- media error (e.g. ICE negotiation failure). 
    155155    """ 
    156     NONE = 0 
     156    NULL = 0 
    157157    ACTIVE = 1 
    158158    LOCAL_HOLD = 2 
     
    166166    Member documentation: 
    167167 
    168     NONE              -- media is not active 
     168    NULL              -- media is not active 
    169169    ENCODING          -- media is active in transmit/encoding direction only. 
    170170    DECODING          -- media is active in receive/decoding direction only 
    171171    ENCODING_DECODING -- media is active in both directions. 
    172172    """ 
    173     NONE = 0 
     173    NULL = 0 
    174174    ENCODING = 1 
    175175    DECODING = 2 
     
    189189    AWAY = 1 
    190190    BUSY = 2 
     191 
     192 
     193class SubscriptionState: 
     194    """Presence subscription state constants. 
     195 
     196    """ 
     197    NULL = 0 
     198    SENT = 1 
     199    ACCEPTED = 2 
     200    PENDING = 3 
     201    ACTIVE = 4 
     202    TERMINATED = 5 
     203    UNKNOWN = 6 
     204 
    191205 
    192206class TURNConnType: 
     
    862876        reject the call with default status code. 
    863877 
    864     Keyword arguments: 
    865     call    -- the new incoming call 
     878        Keyword arguments: 
     879        call    -- the new incoming call 
    866880        """ 
    867881        call.hangup() 
     882 
     883    def on_incoming_subscribe(self, buddy, from_uri, pres_obj): 
     884        """Notification when incoming SUBSCRIBE request is received.  
     885         
     886        Application may use this callback to authorize the incoming  
     887        subscribe request (e.g. ask user permission if the request  
     888        should be granted) 
     889 
     890        Keyword arguments: 
     891        buddy       -- The buddy object, if buddy is found. Otherwise 
     892                       the value is None. 
     893        from_uri    -- The URI string of the sender. 
     894        pres_obj    -- Opaque presence subscription object, which is 
     895                       needed by Account.pres_notify() 
     896 
     897        Return: 
     898            Tuple (code, reason), where: 
     899             code:      The status code. If code is >= 300, the 
     900                        request is rejected. If code is 200, the 
     901                        request is accepted and NOTIFY will be sent 
     902                        automatically. If code is 202, application 
     903                        must accept or reject the request later with 
     904                        Account.press_notify(). 
     905             reason:    Optional reason phrase, or None to use the 
     906                        default reasoh phrase for the status code. 
     907        """ 
     908        return (200, None) 
    868909 
    869910    def on_pager(self, from_uri, contact, mime_type, body): 
     
    952993        id  -- the pjsua account ID. 
    953994        """ 
    954         _cb = AccountCallback(self) 
     995        self._cb = AccountCallback(self) 
    955996        self._id = id 
    956997        self._lib = lib 
     
    11021143        return Buddy(self._lib, buddy_id, self) 
    11031144 
     1145    def pres_notify(self, pres_obj, state, reason="", hdr_list=None): 
     1146        """Send NOTIFY to inform account presence status or to terminate 
     1147        server side presence subscription. 
     1148         
     1149        Keyword arguments: 
     1150        pres_obj    -- The subscription object from on_incoming_subscribe() 
     1151                       callback 
     1152        state       -- Subscription state, from SubscriptionState 
     1153        reason      -- Optional reason phrase. 
     1154        hdr_list    -- Optional header list. 
     1155        """ 
     1156        _pjsua.acc_pres_notify(self._id, pres_obj, state, reason,  
     1157                               Lib._create_msg_data(hdr_list)) 
    11041158 
    11051159class CallCallback: 
     
    12761330    last_code = 0 
    12771331    last_reason = "" 
    1278     media_state = MediaState.NONE 
    1279     media_dir = MediaDir.NONE 
     1332    media_state = MediaState.NULL 
     1333    media_dir = MediaDir.NULL 
    12801334    conf_slot = -1 
    12811335    call_time = 0 
     
    15301584    subscribed      -- specify whether buddy's presence status is currently 
    15311585                       being subscribed. 
     1586    sub_state       -- SubscriptionState 
     1587    sub_term_reason -- The termination reason string of the last presence 
     1588                       subscription to this buddy, if any. 
    15321589    """ 
    15331590    uri = "" 
     
    15371594    activity = PresenceActivity.UNKNOWN 
    15381595    subscribed = False 
     1596    sub_state = SubscriptionState.NULL 
     1597    sub_term_reason = "" 
    15391598 
    15401599    def __init__(self, pjsua_bi=None): 
     
    15491608        self.activity = inf.activity 
    15501609        self.subscribed = inf.monitor_pres 
     1610        self.sub_state = inf.sub_state 
     1611        self.sub_term_reason = inf.sub_term_reason 
    15511612 
    15521613 
     
    18671928        py_ua_cfg.cb.on_call_replaced = _cb_on_call_replaced 
    18681929        py_ua_cfg.cb.on_reg_state = _cb_on_reg_state 
     1930        py_ua_cfg.cb.on_incoming_subscribe = _cb_on_incoming_subscribe 
    18691931        py_ua_cfg.cb.on_buddy_state = _cb_on_buddy_state 
    18701932        py_ua_cfg.cb.on_pager = _cb_on_pager 
     
    22672329 
    22682330    def _lookup_buddy(self, buddy_id, uri=None): 
    2269         print "lookup_buddy, id=", buddy_id 
    22702331        buddy = self.buddy.has_key(buddy_id) and self.buddy[buddy_id] or None 
    22712332        if uri and not buddy: 
    22722333            sip_uri = SIPUri(uri) 
    2273             print "lookup_buddy, uri=", sip_uri.user, sip_uri.host 
    22742334            buddy = self.buddy_by_uri.has_key( (sip_uri.user, sip_uri.host) ) \ 
    22752335                    and self.buddy_by_uri[(sip_uri.user, sip_uri.host)] or \ 
     
    22892349        if acc: 
    22902350            acc._cb.on_reg_state() 
     2351 
     2352    def _cb_on_incoming_subscribe(self, acc_id, buddy_id, from_uri, pres_obj): 
     2353        acc = self._lookup_account(acc_id) 
     2354        if acc: 
     2355            buddy = self._lookup_buddy(buddy_id) 
     2356            return acc._cb.on_incoming_subscribe(buddy, from_uri, pres_obj) 
     2357        else: 
     2358            return (404, None) 
    22912359 
    22922360    def _cb_on_incoming_call(self, acc_id, call_id, rdata): 
     
    24252493    _lib._cb_on_reg_state(acc_id) 
    24262494 
     2495def _cb_on_incoming_subscribe(acc_id, buddy_id, from_uri, pres): 
     2496    return _lib._cb_on_incoming_subscribe(acc_id, buddy_id, from_uri, pres) 
     2497 
    24272498def _cb_on_buddy_state(buddy_id): 
    24282499    _lib._cb_on_buddy_state(buddy_id) 
Note: See TracChangeset for help on using the changeset viewer.