⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smsc_emi.c

📁 The Kannel Open Source WAP and SMS gateway works as both an SMS gateway, for implementing keyword b
💻 C
📖 第 1 页 / 共 4 页
字号:
    	 /* EMI doesnt understand + so we have to replace it with something useful */    	 /* we try 00 here. Should really be done in the config instead so this */    	 /* is only a workaround to make wrong configs work  */	 octstr_delete(str, 0, 1);	 octstr_insert_data(str, 0, "00",2);    }    octstr_truncate(str, 16); /* max length of ADC */    emimsg->fields[E50_ADC] = str;       emimsg->fields[E50_XSER] = octstr_create("");    /* XSer 01: UDH */    if (octstr_len(msg->sms.udhdata)) {        str = octstr_create("");        octstr_append_char(str, 0x01);        octstr_append_char(str, octstr_len(msg->sms.udhdata));        octstr_append(str, msg->sms.udhdata);        octstr_binary_to_hex(str, 1);        octstr_append(emimsg->fields[E50_XSER], str);        octstr_destroy(str);    }	    /* XSer 02: DCS */    dcs = fields_to_dcs(msg, msg->sms.alt_dcs);    if (dcs != 0 && dcs != 4) {        str = octstr_create("");        octstr_append_char(str, 0x02);        octstr_append_char(str, 1); /* len 01 */        octstr_append_char(str, dcs);        octstr_binary_to_hex(str, 1);        octstr_append(emimsg->fields[E50_XSER], str);        octstr_destroy(str);    }    /* XSer 0c: billing identifier */    if (octstr_len(msg->sms.binfo)) {        str = octstr_create("");        octstr_append_char(str, 0x0c);        octstr_append_char(str, octstr_len(msg->sms.binfo));        octstr_append(str, msg->sms.binfo);        octstr_binary_to_hex(str, 1);        octstr_append(emimsg->fields[E50_XSER], str);        octstr_destroy(str);    }    if (msg->sms.coding == DC_8BIT || msg->sms.coding == DC_UCS2) {	emimsg->fields[E50_MT] = octstr_create("4");	emimsg->fields[E50_MCLS] = octstr_create("1");	str = octstr_duplicate(msg->sms.msgdata);	emimsg->fields[E50_NB] =	    octstr_format("%04d", 8 * octstr_len(str));	octstr_binary_to_hex(str, 1);	emimsg->fields[E50_TMSG] = str;    }    else {	emimsg->fields[E50_MT] = octstr_create("3");	str = octstr_duplicate(msg->sms.msgdata);	charset_latin1_to_gsm(str);    /*     * Check if we have to apply some after GSM transcoding kludges     */    if (privdata->alt_charset == EMI_NRC_ISO_21)        charset_gsm_to_nrc_iso_21_german(str);	/* Could still be too long after truncation if there's an UDH part,	 * but this is only to notice errors elsewhere (should never happen).*/	if (charset_gsm_truncate(str, 160))	    error(0, "EMI2[%s]: Message to send is longer "		  "than 160 gsm characters",		  octstr_get_cstr(privdata->name));	octstr_binary_to_hex(str, 1);	emimsg->fields[E50_AMSG] = str;    }    if (msg->sms.validity >= 0) {	tm = gw_localtime(time(NULL) + msg->sms.validity * 60);	sprintf(p, "%02d%02d%02d%02d%02d",	    tm.tm_mday, tm.tm_mon + 1, tm.tm_year % 100, 	    tm.tm_hour, tm.tm_min);	str = octstr_create(p);	emimsg->fields[E50_VP] = str;    }    if (msg->sms.deferred >= 0) {	str = octstr_create("1");	emimsg->fields[E50_DD] = str;	tm = gw_localtime(time(NULL) + msg->sms.deferred * 60);	sprintf(p, "%02d%02d%02d%02d%02d",	    tm.tm_mday, tm.tm_mon + 1, tm.tm_year % 100, 	    tm.tm_hour, tm.tm_min);	str = octstr_create(p);	emimsg->fields[E50_DDT] = str;    }    /* if delivery reports are asked, lets ask for them too */    /* even the sender might not be interested in delivery or non delivery */    /* we still need them back to clear out the memory after the message */    /* has been delivered or non delivery has been confirmed */    if (DLR_IS_ENABLED_DEVICE(msg->sms.dlr_mask)) {	emimsg->fields[E50_NRQ] = octstr_create("1");	emimsg->fields[E50_NT] = octstr_create("");	octstr_append_decimal(emimsg->fields[E50_NT], 3 + (DLR_IS_BUFFERED(msg->sms.dlr_mask) ? 4 : 0));	if (privdata->npid)	    emimsg->fields[E50_NPID] = octstr_duplicate(privdata->npid);	if (privdata->nadc)	    emimsg->fields[E50_NADC] = octstr_duplicate(privdata->nadc);     }    return emimsg;}/* Return -1 if the connection broke, 0 if the request couldn't be handled * (unknown type), or 1 if everything was successful */static int handle_operation(SMSCConn *conn, Connection *server,			   struct emimsg *emimsg){    struct emimsg *reply;    Octstr *tempstr, *xser;    int type, len;    Msg *msg = NULL;    struct universaltime unitime;    int st_code;    PrivData *privdata = conn->data;    switch(emimsg->ot) {    /*     * Handle OP/01 call input operation. This operation delivery MO messages     * from SMSC to SMT according to [1], section 4.2, p. 9.     */    case 01:	msg = msg_create(sms);	if (emimsg->fields[E01_AMSG] == NULL)	    emimsg->fields[E01_AMSG] = octstr_create("");	else if (octstr_hex_to_binary(emimsg->fields[E01_AMSG]) == -1)	    warning(0, "EMI2[%s]: Couldn't decode message text",		    octstr_get_cstr(privdata->name));	if (emimsg->fields[E01_MT] == NULL) {	    warning(0, "EMI2[%s]: required field MT missing",		    octstr_get_cstr(privdata->name));	    /* This guess could be incorrect, maybe the message should just	       be dropped */	    emimsg->fields[E01_MT] = octstr_create("3");	}	if (octstr_get_char(emimsg->fields[E01_MT], 0) == '3') {	    msg->sms.msgdata = emimsg->fields[E01_AMSG];	    emimsg->fields[E01_AMSG] = NULL; /* So it's not freed */        /* obey the NRC (national replacement codes) */        if (privdata->alt_charset == EMI_NRC_ISO_21)            charset_nrc_iso_21_german_to_gsm(msg->sms.msgdata);	    charset_gsm_to_latin1(msg->sms.msgdata);	}	else {	    error(0, "EMI2[%s]: MT == %s isn't supported for operation type 01",		  octstr_get_cstr(privdata->name),		  octstr_get_cstr(emimsg->fields[E01_MT]));	    msg->sms.msgdata = octstr_create("");	}	msg->sms.sender = octstr_duplicate(emimsg->fields[E01_OADC]);	if (msg->sms.sender == NULL) {	    warning(0, "EMI2[%s]: Empty sender field in received message",		    octstr_get_cstr(privdata->name));	    msg->sms.sender = octstr_create("");	}	if(octstr_len(PRIVDATA(conn)->my_number)) {	    msg->sms.receiver = octstr_duplicate(PRIVDATA(conn)->my_number);	}	else {	    msg->sms.receiver = octstr_duplicate(emimsg->fields[E01_ADC]);	}	if (msg->sms.receiver == NULL) {	    warning(0, "EMI2[%s]: Empty receiver field in received message",		    octstr_get_cstr(privdata->name));	    msg->sms.receiver = octstr_create("");	}	/* Operation type 01 doesn't have a time stamp field */	time(&msg->sms.time);	msg->sms.smsc_id = octstr_duplicate(conn->id);	bb_smscconn_receive(conn, msg);	reply = emimsg_create_reply(01, emimsg->trn, 1, privdata->name);	if (emi2_emimsg_send(conn, server, reply) < 0) {	    emimsg_destroy(reply);	    return -1;	}	emimsg_destroy(reply);	return 1;    /*     * Handle OP/52 delivery short message. This is the MO side of the protocol     * implementation. See [1], section 5.4, p. 40.     */    case 52:	msg = msg_create(sms);	/* AMSG is the same field as TMSG */	if (emimsg->fields[E50_AMSG] == NULL)	    emimsg->fields[E50_AMSG] = octstr_create("");	else if (octstr_hex_to_binary(emimsg->fields[E50_AMSG]) == -1)	    warning(0, "EMI2[%s]: Couldn't decode message text",		      octstr_get_cstr(privdata->name));    /* Process XSer fields */	xser = emimsg->fields[E50_XSER];	while (octstr_len(xser) > 0) {        int tempint;	    tempstr = octstr_copy(xser, 0, 4);	    if (octstr_hex_to_binary(tempstr) == -1)		error(0, "EMI2[%s]: Invalid XSer",		      octstr_get_cstr(privdata->name));	    type = octstr_get_char(tempstr, 0);	    len = octstr_get_char(tempstr, 1);	    octstr_destroy(tempstr);	    if (len < 0) {		error(0, "EMI2[%s]: Malformed emi XSer field",		      octstr_get_cstr(privdata->name));		break;	    }        /* Handle supported XSer fields */        switch (type) {            case 0x01:  /* XSer 01, GSM UDH information */                tempstr = octstr_copy(xser, 4, len * 2);                if (octstr_hex_to_binary(tempstr) == -1)                    error(0, "EMI2[%s]: Invalid UDH contents",                          octstr_get_cstr(privdata->name));                msg->sms.udhdata = tempstr;                break;            case 0x02:  /* XSer 02, GSM DCS information */                tempstr = octstr_copy(xser, 4, 2);                octstr_hex_to_binary(tempstr);                tempint = octstr_get_char(tempstr, 0);                octstr_destroy(tempstr);                if (!dcs_to_fields(&msg, tempint)) {                    error(0, "EMI2[%s]: Invalid DCS received",                          octstr_get_cstr(privdata->name));                    /* XXX Should we discard message ? */                    dcs_to_fields(&msg, 0);                }                break;            /*              * XSer 03-0b are for TDMA information exchange and are currently             * not implemented in this EMI interface. See CMG EMI/UCP spec 4.0,             * section 5.1.2.4 for more information.             */            case 0x0c:  /* XSer 0c, billing identifier */                tempstr = octstr_copy(xser, 4, len * 2);                if (octstr_hex_to_binary(tempstr) == -1) {                    error(0, "EMI2[%s] Invalid XSer 0c billing identifier <%s>",                          octstr_get_cstr(privdata->name),                           octstr_get_cstr(tempstr));                } else {                    msg->sms.binfo = tempstr;                }                break;                            case 0x0d:  /* XSer 0d, single shot indicator */                tempstr = octstr_copy(xser, 4, 2);                octstr_hex_to_binary(tempstr);                tempint = octstr_get_char(tempstr, 0);                octstr_destroy(tempstr);                if (tempint)                     info(0, "EMI2[%s]: Single shot indicator set.",                         octstr_get_cstr(privdata->name));                break;            /* XSer fields 0e-ff are reserved for future use. */            default:                warning(0, "EMI2[%s]: Unsupported EMI XSer field %d",                        octstr_get_cstr(privdata->name), type);                break;        }        octstr_delete(xser, 0, 2 * len + 4);	}	if (emimsg->fields[E50_MT] == NULL) {	    warning(0, "EMI2[%s]: required field MT missing",		    octstr_get_cstr(privdata->name));	    /* This guess could be incorrect, maybe the message should just	       be dropped */	    emimsg->fields[E50_MT] = octstr_create("3");	}	if (octstr_get_char(emimsg->fields[E50_MT], 0) == '3') {	    msg->sms.msgdata = emimsg->fields[E50_AMSG];	    emimsg->fields[E50_AMSG] = NULL; /* So it's not freed */        /* obey the NRC (national replacement codes) */        if (privdata->alt_charset == EMI_NRC_ISO_21)            charset_nrc_iso_21_german_to_gsm(msg->sms.msgdata);	    charset_gsm_to_latin1(msg->sms.msgdata);	}	else if (octstr_get_char(emimsg->fields[E50_MT], 0) == '4') {	    msg->sms.msgdata = emimsg->fields[E50_TMSG];	    emimsg->fields[E50_TMSG] = NULL;	}	else {	    error(0, "EMI2[%s]: MT == %s isn't supported yet",		  octstr_get_cstr(privdata->name),		  octstr_get_cstr(emimsg->fields[E50_MT]));	    msg->sms.msgdata = octstr_create("");	}	msg->sms.sender = octstr_duplicate(emimsg->fields[E50_OADC]);	if (msg->sms.sender == NULL) {	    warning(0, "EMI2[%s]: Empty sender field in received message",		    octstr_get_cstr(privdata->name));	    msg->sms.sender = octstr_create("");	}	if(octstr_len(PRIVDATA(conn)->my_number)) {	    msg->sms.receiver = octstr_duplicate(PRIVDATA(conn)->my_number);	}	else {	    msg->sms.receiver = octstr_duplicate(emimsg->fields[E50_ADC]);	}	if (msg->sms.receiver == NULL) {	    warning(0, "EMI2[%s]: Empty receiver field in received message",		    octstr_get_cstr(privdata->name));	    msg->sms.receiver = octstr_create("");	}	tempstr = emimsg->fields[E50_SCTS]; /* Just a shorter name */	if (tempstr == NULL) {	    warning(0, "EMI2[%s]: Received EMI message doesn't have required timestamp",		    octstr_get_cstr(privdata->name));	    goto notime;	}	if (octstr_len(tempstr) != 12) {	    warning(0, "EMI2[%s]: EMI SCTS field must have length 12, now %ld",		    octstr_get_cstr(privdata->name), octstr_len(tempstr));	    goto notime;	}	if (octstr_parse_long(&unitime.second, tempstr, 10, 10) != 12 ||	    (octstr_delete(tempstr, 10, 2),	     octstr_parse_long(&unitime.minute, tempstr, 8, 10) != 10) ||	    (octstr_delete(tempstr, 8, 2),	     octstr_parse_long(&unitime.hour, tempstr, 6, 10) != 8) ||	    (octstr_delete(tempstr, 6, 2),	     octstr_parse_long(&unitime.year, tempstr, 4, 10) != 6) ||	    (octstr_delete(tempstr, 4, 2),	     octstr_parse_long(&unitime.month, tempstr, 2, 10) != 4) ||	    (octstr_delete(tempstr, 2, 2),	     octstr_parse_long(&unitime.day, tempstr, 0, 10) != 2)) {	    error(0, "EMI2[%s]: EMI delivery time stamp looks malformed",		  octstr_get_cstr(privdata->name));	notime:	    time(&msg->sms.time);	}	else {	    unitime.year += 2000; /* Conversion function expects full year */            unitime.month -= 1; /* conversion function expects 0-based months */	    msg->sms.time = date_convert_universal(&unitime);	}	msg->sms.smsc_id = octstr_duplicate(conn->id);	bb_smscconn_receive(conn, msg);	reply = emimsg_create_reply(52, emimsg->trn, 1, privdata->name);	if (emi2_emimsg_send(conn, server, reply) < 0) {	    emimsg_destroy(reply);	    return -1;	}	emimsg_destroy(reply);	return 1;    /*     * Handle OP/53 delivery notification. See [1], section 5.5, p. 43.     */    case 53: 	    	st_code = atoi(octstr_get_cstr(emimsg->fields[E50_DST]));	switch(st_code)	{	case 0: /* delivered */		msg = dlr_find((conn->id ? conn->id : privdata->name),			emimsg->fields[E50_SCTS], /* timestamp */			emimsg->fields[E50_OADC], /* destination */			DLR_SUCCESS);		break;	case 1: /* buffered */		msg = dlr_find((conn->id ? conn->id : privdata->name),			emimsg->fields[E50_SCTS], /* timestamp */			emimsg->fields[E50_OADC], /* destination */			DLR_BUFFERED);		break;	case 2: /* not delivered */		msg = dlr_find((conn->id ? conn->id : privdata->name),			emimsg->fields[E50_SCTS], /* timestamp */			emimsg->fields[E50_OADC], /* destination */			DLR_FAIL);		break;	}	if (msg != NULL) {     	    /*	     * Recode the msg structure with the given msgdata.	     * Note: the DLR URL is delivered in msg->sms.dlr_url already.	     */	    if((emimsg->fields[E50_AMSG]) == NULL)		msg->sms.msgdata = octstr_create("Delivery Report without text");	    else		msg->sms.msgdata = octstr_duplicate(emimsg->fields[E50_AMSG]);	    octstr_hex_to_binary(msg->sms.msgdata);	    bb_smscconn_receive(conn, msg);	}	reply = emimsg_create_reply(53, emimsg->trn, 1, privdata->name);	if (emi2_emimsg_send(conn, server, reply) < 0) {	    emimsg_destroy(reply);	    return -1;	}	emimsg_destroy(reply);	return 1;    /*      * Handle OP/31 from SMSC side. This is not "purely" spec conform since,     * the protocol says "This operation can be used by a SMT to alert the SC.",     * which implies semantically only the opposite way. For the sake of EMI/UCP     * server implementations that send alert messages to SMTs we handle this      * without breaking any core protocol concept.     *     * See [1], section 4.6, p. 19.     */    case 31:        reply = emimsg_create_reply(31, emimsg->trn, 1, privdata->name);        st_code = emi2_emimsg_send(conn, server, reply);        emimsg_destroy(reply);        return (st_code < 0 ? -1 : 1);    default:	error(0, "EMI2[%s]: I don't know how to handle operation type %d", 	      octstr_get_cstr(privdata->name), emimsg->ot);	return 0;    }}/* * get all unacknowledged messages from the ringbuffer and queue them * for retransmission. */static void clear_sent(PrivData *privdata){    int i;    debug("smsc.emi2", 0, "EMI2[%s]: clear_sent called",

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -