mirror of
https://github.com/salexdv/SMSCenter.git
synced 2026-04-24 20:33:45 +02:00
2070 lines
90 KiB
C#
2070 lines
90 KiB
C#
/*
|
|
* EasySMPP - SMPP protocol library for fast and easy
|
|
* SMSC(Short Message Service Centre) client development
|
|
* even for non-telecom guys.
|
|
*
|
|
* Easy to use classes covers all needed functionality
|
|
* for SMS applications developers and Content Providers.
|
|
*
|
|
* Written for .NET 2.0 in C#
|
|
*
|
|
* Copyright (C) 2006 Balan Andrei, http://balan.name
|
|
*
|
|
* Licensed under the terms of the GNU Lesser General Public License:
|
|
* http://www.opensource.org/licenses/lgpl-license.php
|
|
*
|
|
* For further information visit:
|
|
* http://easysmpp.sf.net/
|
|
*
|
|
*
|
|
* "Support Open Source software. What about a donation today?"
|
|
*
|
|
*
|
|
* File Name: SMPPClient.cs
|
|
*
|
|
* File Authors:
|
|
* Balan Name, http://balan.name
|
|
*/
|
|
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
using System.Text;
|
|
using System.Threading;
|
|
|
|
using SMSCenter;
|
|
|
|
namespace SMSCenter
|
|
{
|
|
/// <summary>
|
|
/// Summary description for SMPPClient.
|
|
/// </summary>
|
|
public class SMPPClient
|
|
{
|
|
|
|
#region Private variables
|
|
private Socket clientSocket;
|
|
|
|
private int connectionState;
|
|
|
|
private DateTime enquireLinkSendTime;
|
|
private DateTime enquireLinkResponseTime;
|
|
private DateTime lastSeenConnected;
|
|
private DateTime lastPacketSentTime;
|
|
|
|
private Timer enquireLinkTimer;
|
|
private int undeliveredMessages = 0;
|
|
|
|
private SMSCArray smscArray = new SMSCArray();
|
|
|
|
private byte[] mbResponse = new byte[KernelParameters.MaxBufferSize];
|
|
private int mPos = 0;
|
|
private int mLen = 0;
|
|
|
|
private bool mustBeConnected;
|
|
|
|
private int logLevel = 0;
|
|
private byte askDeliveryReceipt = KernelParameters.AskDeliveryReceipt;
|
|
private bool splitLongText = KernelParameters.SplitLongText;
|
|
private int nationalNumberLength = KernelParameters.NationalNumberLength;
|
|
private bool useEnquireLink = KernelParameters.UseEnquireLink;
|
|
private int enquireLinkTimeout = KernelParameters.EnquireLinkTimeout;
|
|
private int reconnectTimeout = KernelParameters.ReconnectTimeout;
|
|
|
|
private SortedList sarMessages = SortedList.Synchronized(new SortedList());
|
|
#endregion Private variables
|
|
|
|
#region Public Functions
|
|
|
|
private bool writeLog;
|
|
|
|
public bool WriteLog
|
|
{
|
|
get { return writeLog; }
|
|
set { writeLog = value; }
|
|
}
|
|
|
|
public SMPPClient()
|
|
{
|
|
connectionState= ConnectionStates.SMPP_SOCKET_DISCONNECTED;
|
|
|
|
enquireLinkSendTime = DateTime.Now;
|
|
enquireLinkResponseTime = enquireLinkSendTime.AddSeconds(1);
|
|
lastSeenConnected = DateTime.Now;
|
|
lastPacketSentTime = DateTime.MaxValue;
|
|
|
|
mustBeConnected = false;
|
|
|
|
TimerCallback timerDelegate = new TimerCallback(checkSystemIntegrity);
|
|
enquireLinkTimer = new Timer(timerDelegate, null, enquireLinkTimeout, enquireLinkTimeout);
|
|
|
|
}
|
|
|
|
public void Connect()
|
|
{
|
|
try
|
|
{
|
|
mustBeConnected = true;
|
|
connectToSMSC();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "connectToSMSC | " + ex.ToString());
|
|
}
|
|
}//connectToSMSC
|
|
|
|
public void Disconnect()
|
|
{
|
|
try
|
|
{
|
|
mustBeConnected = false;
|
|
unBind();
|
|
disconnectSocket();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "DisconnectFromSMSC | " + ex.ToString());
|
|
}
|
|
}//DisconnectFromSMSC
|
|
|
|
public void ClearSMSC()
|
|
{
|
|
try
|
|
{
|
|
smscArray.Clear();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "AddSMSC | " + ex.ToString());
|
|
}
|
|
|
|
}//ClearSMSC
|
|
|
|
public void AddSMSC(SMSC mSMSC)
|
|
{
|
|
try
|
|
{
|
|
smscArray.AddSMSC(mSMSC);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "AddSMSC | " + ex.ToString());
|
|
}
|
|
|
|
}//AddSMSC
|
|
|
|
#region Send Functions
|
|
|
|
public void Send(byte[] data, int n)
|
|
{
|
|
try
|
|
{
|
|
lastPacketSentTime = DateTime.Now;
|
|
logMessage(LogLevels.LogPdu, "Sending PDU : " + Tools.ConvertArrayToHexString(data, n));
|
|
clientSocket.BeginSend(data, 0, n, 0, new AsyncCallback(sendCallback), clientSocket);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "Send | " + ex.ToString());
|
|
}
|
|
}//Send
|
|
|
|
public int SubmitSM(byte sourceAddressTon, byte sourceAddressNpi, string sourceAddress,
|
|
byte destinationAddressTon, byte destinationAddressNpi, string destinationAddress,
|
|
byte esmClass, byte protocolId, byte priorityFlag,
|
|
DateTime sheduleDeliveryTime, DateTime validityPeriod, byte registeredDelivery,
|
|
byte replaceIfPresentFlag, byte dataCoding, byte smDefaultMsgId,
|
|
byte[] message, int msgID)
|
|
{
|
|
try
|
|
{
|
|
byte[] _destination_addr;
|
|
byte[] _source_addr;
|
|
byte[] _SUBMIT_SM_PDU;
|
|
byte[] _shedule_delivery_time;
|
|
byte[] _validity_period;
|
|
int _sequence_number;
|
|
int pos;
|
|
byte _sm_length;
|
|
|
|
|
|
_SUBMIT_SM_PDU = new byte[KernelParameters.MaxPduSize];
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/// Start filling PDU
|
|
|
|
Tools.CopyIntToArray(0x00000004, _SUBMIT_SM_PDU, 4);
|
|
//_sequence_number = smscArray.currentSMSC.SequenceNumber;
|
|
_sequence_number = msgID;
|
|
Tools.CopyIntToArray(_sequence_number, _SUBMIT_SM_PDU, 12);
|
|
pos = 16;
|
|
_SUBMIT_SM_PDU[pos] = 0x00; //service_type
|
|
pos += 1;
|
|
_SUBMIT_SM_PDU[pos] = sourceAddressTon;
|
|
pos += 1;
|
|
_SUBMIT_SM_PDU[pos] = sourceAddressNpi;
|
|
pos += 1;
|
|
_source_addr = Tools.ConvertStringToByteArray(Tools.GetString(sourceAddress, 20, ""));
|
|
Array.Copy(_source_addr, 0, _SUBMIT_SM_PDU, pos, _source_addr.Length);
|
|
pos += _source_addr.Length;
|
|
_SUBMIT_SM_PDU[pos] = 0x00;
|
|
pos += 1;
|
|
_SUBMIT_SM_PDU[pos] = destinationAddressTon;
|
|
pos += 1;
|
|
_SUBMIT_SM_PDU[pos] = destinationAddressNpi;
|
|
pos += 1;
|
|
_destination_addr = Tools.ConvertStringToByteArray(Tools.GetString(destinationAddress, 20, ""));
|
|
Array.Copy(_destination_addr, 0, _SUBMIT_SM_PDU, pos, _destination_addr.Length);
|
|
pos += _destination_addr.Length;
|
|
_SUBMIT_SM_PDU[pos] = 0x00;
|
|
pos += 1;
|
|
_SUBMIT_SM_PDU[pos] = esmClass;
|
|
pos += 1;
|
|
_SUBMIT_SM_PDU[pos] = protocolId;
|
|
pos += 1;
|
|
_SUBMIT_SM_PDU[pos] = priorityFlag;
|
|
pos += 1;
|
|
_shedule_delivery_time = Tools.ConvertStringToByteArray(Tools.GetDateString(sheduleDeliveryTime));
|
|
Array.Copy(_shedule_delivery_time, 0, _SUBMIT_SM_PDU, pos, _shedule_delivery_time.Length);
|
|
pos += _shedule_delivery_time.Length;
|
|
_SUBMIT_SM_PDU[pos] = 0x00;
|
|
pos += 1;
|
|
_validity_period = Tools.ConvertStringToByteArray(Tools.GetDateString(validityPeriod));
|
|
Array.Copy(_validity_period, 0, _SUBMIT_SM_PDU, pos, _validity_period.Length);
|
|
pos += _validity_period.Length;
|
|
_SUBMIT_SM_PDU[pos] = 0x00;
|
|
pos += 1;
|
|
_SUBMIT_SM_PDU[pos] = registeredDelivery;
|
|
pos += 1;
|
|
_SUBMIT_SM_PDU[pos] = replaceIfPresentFlag;
|
|
pos += 1;
|
|
_SUBMIT_SM_PDU[pos] = dataCoding;
|
|
pos += 1;
|
|
_SUBMIT_SM_PDU[pos] = smDefaultMsgId;
|
|
pos += 1;
|
|
|
|
_sm_length = message.Length > 254 ? (byte)254 : (byte)message.Length;
|
|
|
|
_SUBMIT_SM_PDU[pos] = _sm_length;
|
|
pos += 1;
|
|
Array.Copy(message, 0, _SUBMIT_SM_PDU, pos, _sm_length);
|
|
pos += _sm_length;
|
|
|
|
Tools.CopyIntToArray(pos, _SUBMIT_SM_PDU, 0);
|
|
|
|
Send(_SUBMIT_SM_PDU, pos);
|
|
undeliveredMessages++;
|
|
return _sequence_number;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "SubmitSM | " + ex.ToString());
|
|
}
|
|
return -1;
|
|
|
|
}//SubmitSM
|
|
|
|
public int SubmitSM_LongMessage(byte sourceAddressTon, byte sourceAddressNpi, string sourceAddress,
|
|
byte destinationAddressTon, byte destinationAddressNpi, string destinationAddress,
|
|
byte esmClass, byte protocolId, byte priorityFlag,
|
|
DateTime sheduleDeliveryTime, DateTime validityPeriod, byte registeredDelivery,
|
|
byte replaceIfPresentFlag, byte dataCoding, byte smDefaultMsgId,
|
|
byte[] message, int msgID)
|
|
{
|
|
try
|
|
{
|
|
byte[] _destination_addr;
|
|
byte[] _source_addr;
|
|
byte[] _SUBMIT_SM_PDU;
|
|
byte[] _shedule_delivery_time;
|
|
byte[] _validity_period;
|
|
int _sequence_number;
|
|
int pos;
|
|
byte _sm_length;
|
|
|
|
|
|
_SUBMIT_SM_PDU = new byte[KernelParameters.MaxPduSize];
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/// Start filling PDU
|
|
|
|
Tools.CopyIntToArray(0x00000004, _SUBMIT_SM_PDU, 4);
|
|
_sequence_number = msgID;
|
|
Tools.CopyIntToArray(_sequence_number, _SUBMIT_SM_PDU, 12);
|
|
pos = 16;
|
|
_SUBMIT_SM_PDU[pos] = 0x00; //service_type
|
|
pos += 1;
|
|
_SUBMIT_SM_PDU[pos] = sourceAddressTon;
|
|
pos += 1;
|
|
_SUBMIT_SM_PDU[pos] = sourceAddressNpi;
|
|
pos += 1;
|
|
_source_addr = Tools.ConvertStringToByteArray(Tools.GetString(sourceAddress, 20, ""));
|
|
Array.Copy(_source_addr, 0, _SUBMIT_SM_PDU, pos, _source_addr.Length);
|
|
pos += _source_addr.Length;
|
|
_SUBMIT_SM_PDU[pos] = 0x00;
|
|
pos += 1;
|
|
_SUBMIT_SM_PDU[pos] = destinationAddressTon;
|
|
pos += 1;
|
|
_SUBMIT_SM_PDU[pos] = destinationAddressNpi;
|
|
pos += 1;
|
|
_destination_addr = Tools.ConvertStringToByteArray(Tools.GetString(destinationAddress, 20, ""));
|
|
Array.Copy(_destination_addr, 0, _SUBMIT_SM_PDU, pos, _destination_addr.Length);
|
|
pos += _destination_addr.Length;
|
|
_SUBMIT_SM_PDU[pos] = 0x00;
|
|
pos += 1;
|
|
_SUBMIT_SM_PDU[pos] = esmClass;
|
|
pos += 1;
|
|
_SUBMIT_SM_PDU[pos] = protocolId;
|
|
pos += 1;
|
|
_SUBMIT_SM_PDU[pos] = priorityFlag;
|
|
pos += 1;
|
|
_shedule_delivery_time = Tools.ConvertStringToByteArray(Tools.GetDateString(sheduleDeliveryTime));
|
|
Array.Copy(_shedule_delivery_time, 0, _SUBMIT_SM_PDU, pos, _shedule_delivery_time.Length);
|
|
pos += _shedule_delivery_time.Length;
|
|
_SUBMIT_SM_PDU[pos] = 0x00;
|
|
pos += 1;
|
|
_validity_period = Tools.ConvertStringToByteArray(Tools.GetDateString(validityPeriod));
|
|
Array.Copy(_validity_period, 0, _SUBMIT_SM_PDU, pos, _validity_period.Length);
|
|
pos += _validity_period.Length;
|
|
_SUBMIT_SM_PDU[pos] = 0x00;
|
|
pos += 1;
|
|
_SUBMIT_SM_PDU[pos] = registeredDelivery;
|
|
pos += 1;
|
|
_SUBMIT_SM_PDU[pos] = replaceIfPresentFlag;
|
|
pos += 1;
|
|
_SUBMIT_SM_PDU[pos] = dataCoding;
|
|
pos += 1;
|
|
_SUBMIT_SM_PDU[pos] = smDefaultMsgId;
|
|
pos += 1;
|
|
|
|
_SUBMIT_SM_PDU[pos] = 0x00; // Ñîîáùåíèå ïåðåäàåòñÿ ÷åðåç message_payload, ïîýòîìó sm_length = 0
|
|
pos += 1;
|
|
// short_massage îïóñêàåì
|
|
// TLV message_payload
|
|
// Parameter Tag
|
|
Tools.CopyIntToArrayTwoOctet(0x0424, _SUBMIT_SM_PDU, pos);
|
|
pos += 2;
|
|
// Length
|
|
_sm_length = message.Length > 254 ? (byte)254 : (byte)message.Length;
|
|
Tools.CopyIntToArrayTwoOctet(_sm_length, _SUBMIT_SM_PDU, pos);
|
|
pos += 2;
|
|
// Value
|
|
Array.Copy(message, 0, _SUBMIT_SM_PDU, pos, _sm_length);
|
|
pos += _sm_length;
|
|
|
|
Tools.CopyIntToArray(pos, _SUBMIT_SM_PDU, 0);
|
|
|
|
Send(_SUBMIT_SM_PDU, pos);
|
|
undeliveredMessages++;
|
|
return _sequence_number;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "SubmitSM (long message)| " + ex.ToString());
|
|
}
|
|
return -1;
|
|
|
|
}//SubmitSM
|
|
|
|
public int DataSM(byte sourceAddressTon, byte sourceAddressNpi, string sourceAddress,
|
|
byte destinationAddressTon, byte destinationAddressNpi, string destinationAddress,
|
|
byte esmClass,
|
|
byte registeredDelivery,
|
|
byte dataCoding,
|
|
byte[] data)
|
|
{
|
|
try
|
|
{
|
|
byte[] _destination_addr;
|
|
byte[] _source_addr;
|
|
byte[] _DATA_SM_PDU;
|
|
int _sequence_number;
|
|
int pos;
|
|
Int16 _sm_length;
|
|
|
|
|
|
_DATA_SM_PDU = new byte[KernelParameters.MaxPduSize];
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/// Start filling PDU
|
|
|
|
Tools.CopyIntToArray(0x00000103, _DATA_SM_PDU, 4);
|
|
_sequence_number = smscArray.currentSMSC.SequenceNumber;
|
|
Tools.CopyIntToArray(_sequence_number, _DATA_SM_PDU, 12);
|
|
pos = 16;
|
|
_DATA_SM_PDU[pos] = 0x00; //service_type
|
|
pos += 1;
|
|
_DATA_SM_PDU[pos] = sourceAddressTon;
|
|
pos += 1;
|
|
_DATA_SM_PDU[pos] = sourceAddressNpi;
|
|
pos += 1;
|
|
_source_addr = Tools.ConvertStringToByteArray(Tools.GetString(sourceAddress, 20, ""));
|
|
Array.Copy(_source_addr, 0, _DATA_SM_PDU, pos, _source_addr.Length);
|
|
pos += _source_addr.Length;
|
|
_DATA_SM_PDU[pos] = 0x00;
|
|
pos += 1;
|
|
_DATA_SM_PDU[pos] = destinationAddressTon;
|
|
pos += 1;
|
|
_DATA_SM_PDU[pos] = destinationAddressNpi;
|
|
pos += 1;
|
|
_destination_addr = Tools.ConvertStringToByteArray(Tools.GetString(destinationAddress, 20, ""));
|
|
Array.Copy(_destination_addr, 0, _DATA_SM_PDU, pos, _destination_addr.Length);
|
|
pos += _destination_addr.Length;
|
|
_DATA_SM_PDU[pos] = 0x00;
|
|
pos += 1;
|
|
_DATA_SM_PDU[pos] = esmClass;
|
|
pos += 1;
|
|
_DATA_SM_PDU[pos] = registeredDelivery;
|
|
pos += 1;
|
|
_DATA_SM_PDU[pos] = dataCoding;
|
|
pos += 1;
|
|
|
|
_DATA_SM_PDU[pos] = 0x04;
|
|
pos += 1;
|
|
_DATA_SM_PDU[pos] = 0x24;
|
|
pos += 1;
|
|
|
|
_sm_length = data.Length > 32767 ? (Int16)32767 : (Int16)data.Length;
|
|
|
|
_DATA_SM_PDU[pos] = BitConverter.GetBytes(_sm_length)[1];
|
|
pos += 1;
|
|
_DATA_SM_PDU[pos] = BitConverter.GetBytes(_sm_length)[0];
|
|
pos += 1;
|
|
Array.Copy(data, 0, _DATA_SM_PDU, pos, _sm_length);
|
|
pos += _sm_length;
|
|
|
|
Tools.CopyIntToArray(pos, _DATA_SM_PDU, 0);
|
|
|
|
Send(_DATA_SM_PDU, pos);
|
|
undeliveredMessages++;
|
|
return _sequence_number;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "DataSM | " + ex.ToString());
|
|
}
|
|
return -1;
|
|
|
|
}//DataSM
|
|
|
|
public int DeliverSM(byte sourceAddressTon, byte sourceAddressNpi, string sourceAddress,
|
|
byte destinationAddressTon, byte destinationAddressNpi, string destinationAddress,
|
|
byte esmClass,
|
|
byte registeredDelivery,
|
|
byte dataCoding,
|
|
byte[] message)
|
|
{
|
|
try
|
|
{
|
|
byte[] _destination_addr;
|
|
byte[] _source_addr;
|
|
byte[] _DATA_SM_PDU;
|
|
int _sequence_number;
|
|
int pos;
|
|
byte _sm_length;
|
|
|
|
|
|
_DATA_SM_PDU = new byte[KernelParameters.MaxPduSize];
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/// Start filling PDU
|
|
|
|
Tools.CopyIntToArray(0x00000005, _DATA_SM_PDU, 4);
|
|
_sequence_number = smscArray.currentSMSC.SequenceNumber;
|
|
Tools.CopyIntToArray(_sequence_number, _DATA_SM_PDU, 12);
|
|
pos = 16;
|
|
_DATA_SM_PDU[pos] = 0x00; //service_type
|
|
pos += 1;
|
|
_DATA_SM_PDU[pos] = sourceAddressTon;
|
|
pos += 1;
|
|
_DATA_SM_PDU[pos] = sourceAddressNpi;
|
|
pos += 1;
|
|
_source_addr = Tools.ConvertStringToByteArray(Tools.GetString(sourceAddress, 20, ""));
|
|
Array.Copy(_source_addr, 0, _DATA_SM_PDU, pos, _source_addr.Length);
|
|
pos += _source_addr.Length;
|
|
_DATA_SM_PDU[pos] = 0x00;
|
|
pos += 1;
|
|
_DATA_SM_PDU[pos] = destinationAddressTon;
|
|
pos += 1;
|
|
_DATA_SM_PDU[pos] = destinationAddressNpi;
|
|
pos += 1;
|
|
_destination_addr = Tools.ConvertStringToByteArray(Tools.GetString(destinationAddress, 20, ""));
|
|
Array.Copy(_destination_addr, 0, _DATA_SM_PDU, pos, _destination_addr.Length);
|
|
pos += _destination_addr.Length;
|
|
_DATA_SM_PDU[pos] = 0x00;
|
|
pos += 1;
|
|
_DATA_SM_PDU[pos] = esmClass;
|
|
pos += 1;
|
|
_DATA_SM_PDU[pos] = 0x01; // protocol_id
|
|
pos += 1;
|
|
_DATA_SM_PDU[pos] = 0x00; // priority_flag
|
|
pos += 1;
|
|
_DATA_SM_PDU[pos] = 0x00; // schedule_delivery_time NULL
|
|
pos += 1;
|
|
_DATA_SM_PDU[pos] = 0x00; // validity_period NULL
|
|
pos += 1;
|
|
_DATA_SM_PDU[pos] = 0x01; // registered_delivery
|
|
pos += 1;
|
|
_DATA_SM_PDU[pos] = 0x00; // replace_if_present_flag NULL
|
|
pos += 1;
|
|
_DATA_SM_PDU[pos] = dataCoding;
|
|
pos += 1;
|
|
_DATA_SM_PDU[pos] = 0x00; // sm_default_msg_id NULL
|
|
pos += 1;
|
|
|
|
_sm_length = message.Length > 254 ? (byte)254 : (byte)message.Length;
|
|
|
|
_DATA_SM_PDU[pos] = _sm_length;
|
|
pos += 1;
|
|
Array.Copy(message, 0, _DATA_SM_PDU, pos, _sm_length);
|
|
pos += _sm_length;
|
|
|
|
Tools.CopyIntToArray(pos, _DATA_SM_PDU, 0);
|
|
|
|
Send(_DATA_SM_PDU, pos);
|
|
undeliveredMessages++;
|
|
return _sequence_number;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "DataSM | " + ex.ToString());
|
|
}
|
|
return -1;
|
|
|
|
}//DataSM
|
|
|
|
public int SendLongSms(String from, String to, String text, int msgID)
|
|
{
|
|
return SendLongSms(from, to, splitLongText, text, msgID, askDeliveryReceipt);
|
|
}//SendLongSms
|
|
|
|
public int SendLongSms(String from, String to, String text, int msgID, byte askDeliveryReceipt)
|
|
{
|
|
return SendLongSms(from, to, splitLongText, text, msgID, askDeliveryReceipt);
|
|
}//SendLongSms
|
|
|
|
public int SendLongSms(String from, String to, bool splitLongText, String text, int msgID)
|
|
{
|
|
return SendLongSms(from, to, splitLongText, text, msgID, askDeliveryReceipt);
|
|
}//SendLongSms
|
|
|
|
public int SendLongSms(String from, String to, bool splitLongText, String text, int msgID, byte askDeliveryReceipt)
|
|
{
|
|
return SendLongSms(from, to, splitLongText, text, msgID, askDeliveryReceipt, 0, Tools.GetDataCoding(text));
|
|
}
|
|
|
|
public int SendLongSms(String from, String to, bool splitLongText, String text, int msgID, byte askDeliveryReceipt, byte esmClass, byte dataCoding)
|
|
{
|
|
int messageId = -1;
|
|
byte sourceAddressTon;
|
|
byte sourceAddressNpi;
|
|
string sourceAddress;
|
|
byte destinationAddressTon;
|
|
byte destinationAddressNpi;
|
|
string destinationAddress;
|
|
byte registeredDelivery;
|
|
byte maxLength;
|
|
|
|
sourceAddress = Tools.GetString(from, 20, "");
|
|
sourceAddressTon = getAddrTon(sourceAddress);
|
|
sourceAddressNpi = getAddrNpi(sourceAddress);
|
|
|
|
destinationAddress = Tools.GetString(to, 20, "");
|
|
destinationAddressTon = getAddrTon(destinationAddress);
|
|
destinationAddressNpi = getAddrNpi(destinationAddress);
|
|
|
|
registeredDelivery = askDeliveryReceipt;
|
|
|
|
if (dataCoding == 8)
|
|
{
|
|
text = Tools.Endian2UTF(text);
|
|
}
|
|
|
|
maxLength = 160;
|
|
|
|
if ((text.Length <= maxLength) || (splitLongText))
|
|
{
|
|
byte protocolId;
|
|
byte priorityFlag;
|
|
DateTime sheduleDeliveryTime;
|
|
DateTime validityPeriod;
|
|
byte replaceIfPresentFlag;
|
|
byte smDefaultMsgId;
|
|
byte[] message;
|
|
string smsText = text;
|
|
|
|
protocolId = 0;
|
|
priorityFlag = PriorityFlags.VeryUrgent;
|
|
sheduleDeliveryTime = DateTime.MinValue;
|
|
validityPeriod = DateTime.MinValue;
|
|
replaceIfPresentFlag = ReplaceIfPresentFlags.DoNotReplace;
|
|
smDefaultMsgId = 0;
|
|
|
|
while (smsText.Length > 0)
|
|
{
|
|
if (dataCoding == 8)
|
|
message = Encoding.UTF8.GetBytes(smsText.Substring(0, smsText.Length > maxLength ? maxLength : smsText.Length));
|
|
else
|
|
message = Encoding.ASCII.GetBytes(smsText.Substring(0, smsText.Length > maxLength ? maxLength : smsText.Length));
|
|
|
|
smsText = smsText.Remove(0, smsText.Length > maxLength ? maxLength : smsText.Length);
|
|
|
|
messageId = SubmitSM_LongMessage(sourceAddressTon, sourceAddressNpi, sourceAddress,
|
|
destinationAddressTon, destinationAddressNpi, destinationAddress,
|
|
esmClass, protocolId, priorityFlag,
|
|
sheduleDeliveryTime, validityPeriod, registeredDelivery, replaceIfPresentFlag,
|
|
dataCoding, smDefaultMsgId, message, msgID);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
byte[] data;
|
|
|
|
if (dataCoding == 8)
|
|
data = Encoding.UTF8.GetBytes(text);
|
|
else
|
|
data = Encoding.ASCII.GetBytes(text);
|
|
messageId = DataSM(sourceAddressTon, sourceAddressNpi, sourceAddress,
|
|
destinationAddressTon, destinationAddressNpi, destinationAddress,
|
|
esmClass, registeredDelivery, dataCoding, data);
|
|
}
|
|
return messageId;
|
|
}//SendLongSms
|
|
|
|
|
|
public int SendSms(String from, String to, String text, int msgID)
|
|
{
|
|
return SendSms(from, to, splitLongText, text, msgID, askDeliveryReceipt);
|
|
}//SendSms
|
|
public int SendSms(String from, String to, String text, int msgID, byte askDeliveryReceipt)
|
|
{
|
|
return SendSms(from, to, splitLongText, text, msgID, askDeliveryReceipt);
|
|
}//SendSms
|
|
public int SendSms(String from, String to, bool splitLongText, String text, int msgID)
|
|
{
|
|
return SendSms(from, to, splitLongText, text, msgID, askDeliveryReceipt);
|
|
}//SendSms
|
|
public int SendSms(String from, String to, bool splitLongText, String text, int msgID, byte askDeliveryReceipt)
|
|
{
|
|
return SendSms(from, to, splitLongText, text, msgID, askDeliveryReceipt, 0, Tools.GetDataCoding(text));
|
|
}
|
|
|
|
public int SendSms(String from, String to, bool splitLongText, String text, int msgID, byte askDeliveryReceipt, byte esmClass, byte dataCoding)
|
|
{
|
|
int messageId = -1;
|
|
byte sourceAddressTon;
|
|
byte sourceAddressNpi;
|
|
string sourceAddress;
|
|
byte destinationAddressTon;
|
|
byte destinationAddressNpi;
|
|
string destinationAddress;
|
|
byte registeredDelivery;
|
|
byte maxLength;
|
|
|
|
sourceAddress = Tools.GetString(from, 20, "");
|
|
sourceAddressTon = getAddrTon(sourceAddress);
|
|
sourceAddressNpi = getAddrNpi(sourceAddress);
|
|
|
|
destinationAddress = Tools.GetString(to, 20, "");
|
|
destinationAddressTon = getAddrTon(destinationAddress);
|
|
destinationAddressNpi = getAddrNpi(destinationAddress);
|
|
|
|
registeredDelivery = askDeliveryReceipt;
|
|
|
|
if (dataCoding == 8)
|
|
{
|
|
text = Tools.Endian2UTF(text);
|
|
maxLength = 70;
|
|
}
|
|
else
|
|
maxLength = 160;
|
|
|
|
if ((text.Length <= maxLength) || (splitLongText))
|
|
{
|
|
byte protocolId;
|
|
byte priorityFlag;
|
|
DateTime sheduleDeliveryTime;
|
|
DateTime validityPeriod;
|
|
byte replaceIfPresentFlag;
|
|
byte smDefaultMsgId;
|
|
byte[] message;
|
|
string smsText = text;
|
|
|
|
protocolId = 0;
|
|
priorityFlag = PriorityFlags.VeryUrgent;
|
|
sheduleDeliveryTime = DateTime.MinValue;
|
|
validityPeriod = DateTime.MinValue;
|
|
replaceIfPresentFlag = ReplaceIfPresentFlags.DoNotReplace;
|
|
smDefaultMsgId = 0;
|
|
|
|
while (smsText.Length > 0)
|
|
{
|
|
if (dataCoding == 8)
|
|
message = Encoding.UTF8.GetBytes(smsText.Substring(0, smsText.Length > maxLength ? maxLength : smsText.Length));
|
|
else
|
|
message = Encoding.ASCII.GetBytes(smsText.Substring(0, smsText.Length > maxLength ? maxLength : smsText.Length));
|
|
|
|
smsText = smsText.Remove(0, smsText.Length > maxLength ? maxLength : smsText.Length);
|
|
|
|
messageId = SubmitSM(sourceAddressTon, sourceAddressNpi, sourceAddress,
|
|
destinationAddressTon, destinationAddressNpi, destinationAddress,
|
|
esmClass, protocolId, priorityFlag,
|
|
sheduleDeliveryTime, validityPeriod, registeredDelivery, replaceIfPresentFlag,
|
|
dataCoding, smDefaultMsgId, message, msgID);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
byte[] data;
|
|
|
|
if (dataCoding == 8)
|
|
data = Encoding.UTF8.GetBytes(text);
|
|
else
|
|
data = Encoding.ASCII.GetBytes(text);
|
|
messageId = DataSM(sourceAddressTon, sourceAddressNpi, sourceAddress,
|
|
destinationAddressTon, destinationAddressNpi, destinationAddress,
|
|
esmClass, registeredDelivery, dataCoding, data);
|
|
}
|
|
return messageId;
|
|
}//SendSms
|
|
public int SendFlashSms(String from, String to, String text)
|
|
{
|
|
return SendFlashSms(from, to, text, askDeliveryReceipt);
|
|
}//SendFlashSms
|
|
public int SendFlashSms(String from, String to, String text, byte askDeliveryReceipt)
|
|
{
|
|
return SendSms(from, to, false, text.Substring(0, text.Length > 160 ? 160 : text.Length), 0, askDeliveryReceipt, 0, 0x10);
|
|
}//SendFlashSms
|
|
public int SendMedia(String from, String to, byte[] media)
|
|
{
|
|
return SendMedia(from, to, media, askDeliveryReceipt);
|
|
}//SendMedia
|
|
public int SendMedia(String from, String to, byte[] media, byte askDeliveryReceipt)
|
|
{
|
|
return SendData(from, to, media, 0x40, 0xF5, askDeliveryReceipt);
|
|
}//SendMedia
|
|
public int SendData(String from, String to, byte[] data)
|
|
{
|
|
return SendData(from, to, data, askDeliveryReceipt);
|
|
}//SendData
|
|
public int SendData(String from, String to, byte[] data, byte askDeliveryReceipt)
|
|
{
|
|
return SendData(from, to, data, 0, 0, 0);
|
|
}//SendData
|
|
public int SendData(String from, String to, byte[] data, byte esmClass, byte dataCoding, byte askDeliveryReceipt)
|
|
{
|
|
int messageId;
|
|
byte sourceAddressTon;
|
|
byte sourceAddressNpi;
|
|
string sourceAddress;
|
|
byte destinationAddressTon;
|
|
byte destinationAddressNpi;
|
|
string destinationAddress;
|
|
byte registeredDelivery;
|
|
|
|
sourceAddress = Tools.GetString(from, 20, "");
|
|
sourceAddressTon = getAddrTon(sourceAddress);
|
|
sourceAddressNpi = getAddrNpi(sourceAddress);
|
|
|
|
destinationAddress = Tools.GetString(from, 20, "");
|
|
destinationAddressTon = getAddrTon(destinationAddress);
|
|
destinationAddressNpi = getAddrNpi(destinationAddress);
|
|
|
|
registeredDelivery = askDeliveryReceipt;
|
|
|
|
messageId = DataSM(sourceAddressTon, sourceAddressNpi, sourceAddress,
|
|
destinationAddressTon, destinationAddressNpi, destinationAddress,
|
|
esmClass, registeredDelivery, dataCoding, data);
|
|
|
|
return messageId;
|
|
}//SendData
|
|
|
|
#endregion New Send Functions
|
|
|
|
#endregion Public Functions
|
|
|
|
#region Properties
|
|
public bool CanSend
|
|
{
|
|
get
|
|
{
|
|
try
|
|
{
|
|
if ((connectionState== ConnectionStates.SMPP_BINDED) && (undeliveredMessages <= KernelParameters.MaxUndeliverableMessages))
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "CanSend | " + ex.ToString());
|
|
}
|
|
return false;
|
|
}
|
|
}//CanSend
|
|
|
|
public int LogLevel
|
|
{
|
|
get
|
|
{
|
|
return logLevel;
|
|
}
|
|
set
|
|
{
|
|
logLevel = value;
|
|
}
|
|
}//CanSend
|
|
|
|
|
|
public byte AskDeliveryReceipt
|
|
{
|
|
get
|
|
{
|
|
return askDeliveryReceipt;
|
|
}
|
|
set
|
|
{
|
|
if ((value < 3) && (value >= 0))
|
|
askDeliveryReceipt = value;
|
|
}
|
|
}//AskDeliveryReceipt
|
|
|
|
public bool SplitLongText
|
|
{
|
|
get
|
|
{
|
|
return splitLongText;
|
|
}
|
|
set
|
|
{
|
|
splitLongText = value;
|
|
}
|
|
}//SplitLongText
|
|
public int NationalNumberLength
|
|
{
|
|
get
|
|
{
|
|
return nationalNumberLength;
|
|
}
|
|
set
|
|
{
|
|
if (value <= 12)
|
|
nationalNumberLength = value;
|
|
}
|
|
}//NationalNumberLength
|
|
public bool UseEnquireLink
|
|
{
|
|
get
|
|
{
|
|
return useEnquireLink;
|
|
}
|
|
set
|
|
{
|
|
useEnquireLink = value;
|
|
}
|
|
}//UseEnquireLink
|
|
public int EnquireLinkTimeout
|
|
{
|
|
get
|
|
{
|
|
return enquireLinkTimeout;
|
|
}
|
|
set
|
|
{
|
|
if (value > 1000)
|
|
enquireLinkTimeout = value;
|
|
}
|
|
}//EnquireLinkTimeout
|
|
public int ReconnectTimeout
|
|
{
|
|
get
|
|
{
|
|
return reconnectTimeout;
|
|
}
|
|
set
|
|
{
|
|
if (value > 1000)
|
|
reconnectTimeout = value;
|
|
}
|
|
}//ReconnectTimeout
|
|
|
|
#endregion Properties
|
|
|
|
#region Events
|
|
|
|
public event SubmitSmRespEventHandler OnSubmitSmResp;
|
|
|
|
public event DeliverSmEventHandler OnDeliverSm;
|
|
|
|
public event LogEventHandler OnLog;
|
|
|
|
#endregion Events
|
|
|
|
#region Private functions
|
|
private void connectToSMSC()
|
|
{
|
|
try
|
|
{
|
|
if (!smscArray.HasItems)
|
|
{
|
|
logMessage(LogLevels.LogErrors, "Connect | ERROR #1011 : No SMSC defined. Please ddd SMSC definition first.");
|
|
return;
|
|
}
|
|
initClientParameters();
|
|
|
|
IPAddress ipAddress = IPAddress.Parse(smscArray.currentSMSC.Host);
|
|
IPEndPoint remoteEP = new IPEndPoint(ipAddress, smscArray.currentSMSC.Port);
|
|
// Create a TCP/IP socket.
|
|
//Try to disconnect if connected
|
|
tryToDisconnect();
|
|
clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
|
|
|
logMessage(LogLevels.LogSteps, "Trying to connect to " + smscArray.currentSMSC.Description + "[" + smscArray.currentSMSC.Host + ":" + smscArray.currentSMSC.Port + "]");
|
|
clientSocket.BeginConnect(remoteEP, new AsyncCallback(connectCallback), clientSocket);
|
|
connectionState= ConnectionStates.SMPP_SOCKET_CONNECT_SENT;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "connectToSMSC | " + ex.ToString());
|
|
}
|
|
|
|
}//connectToSMSC
|
|
|
|
private void tryToDisconnect()
|
|
{
|
|
try
|
|
{
|
|
if (clientSocket != null)
|
|
{
|
|
if (clientSocket.Connected)
|
|
{
|
|
clientSocket.Shutdown(SocketShutdown.Both);
|
|
}
|
|
clientSocket = null;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "tryToDisconnect | " + ex.ToString());
|
|
}
|
|
}//tryToDisconnect
|
|
|
|
private void disconnectSocket()
|
|
{
|
|
try
|
|
{
|
|
logMessage(LogLevels.LogSteps, "Disconnected");
|
|
connectionState= ConnectionStates.SMPP_SOCKET_DISCONNECTED;
|
|
clientSocket.Shutdown(SocketShutdown.Both);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "disconnectSocket | " + ex.ToString());
|
|
}
|
|
}//disconnectSocket
|
|
|
|
private void disconnect(Socket client)
|
|
{
|
|
try
|
|
{
|
|
logMessage(LogLevels.LogSteps, "Disconnected");
|
|
connectionState= ConnectionStates.SMPP_SOCKET_DISCONNECTED;
|
|
client.Shutdown(SocketShutdown.Both);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "disconnect | " + ex.ToString());
|
|
}
|
|
}//Disconnect
|
|
|
|
|
|
private void receive()
|
|
{
|
|
try
|
|
{
|
|
// Create the state object.
|
|
StateObject state = new StateObject();
|
|
state.workSocket = clientSocket;
|
|
|
|
// Begin receiving the data from the remote device.
|
|
clientSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
|
|
new AsyncCallback(receiveCallback), state);
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "receive | " + ex.ToString());
|
|
}
|
|
|
|
}//receive
|
|
|
|
private void bind()
|
|
{
|
|
try
|
|
{
|
|
byte[] Bind_PDU = new byte[1024];
|
|
int pos, i, n;
|
|
|
|
pos = 7;
|
|
Bind_PDU[pos] = 0x09;
|
|
|
|
pos = 12;
|
|
Tools.CopyIntToArray(smscArray.currentSMSC.SequenceNumber, Bind_PDU, pos);
|
|
pos = 15;
|
|
|
|
pos++;
|
|
n = smscArray.currentSMSC.SystemId.Length;
|
|
for (i = 0; i < n; i++, pos++)
|
|
Bind_PDU[pos] = (byte)smscArray.currentSMSC.SystemId[i];
|
|
Bind_PDU[pos] = 0;
|
|
|
|
pos++;
|
|
n = smscArray.currentSMSC.Password.Length;
|
|
for (i = 0; i < n; i++, pos++)
|
|
Bind_PDU[pos] = (byte)smscArray.currentSMSC.Password[i];
|
|
Bind_PDU[pos] = 0;
|
|
|
|
pos++;
|
|
n = smscArray.currentSMSC.SystemType.Length;
|
|
for (i = 0; i < n; i++, pos++)
|
|
Bind_PDU[pos] = (byte)smscArray.currentSMSC.SystemType[i];
|
|
Bind_PDU[pos] = 0;
|
|
|
|
Bind_PDU[++pos] = 0x34; //interface version
|
|
Bind_PDU[++pos] = (byte)smscArray.currentSMSC.AddrTon; //addr_ton
|
|
Bind_PDU[++pos] = (byte)smscArray.currentSMSC.AddrNpi; //addr_npi
|
|
|
|
//address_range
|
|
pos++;
|
|
n = smscArray.currentSMSC.AddressRange.Length;
|
|
for (i = 0; i < n; i++, pos++)
|
|
Bind_PDU[pos] = (byte)smscArray.currentSMSC.AddressRange[i];
|
|
Bind_PDU[pos] = 0x00;
|
|
|
|
pos++;
|
|
Bind_PDU[3] = Convert.ToByte(pos & 0x00FF);
|
|
Bind_PDU[2] = Convert.ToByte((pos >> 8) & 0x00FF);
|
|
|
|
// Begin sending the data to the remote device.
|
|
logMessage(LogLevels.LogSteps, "BindSent");
|
|
Send(Bind_PDU, pos);
|
|
connectionState= ConnectionStates.SMPP_BIND_SENT;
|
|
receive();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "bind | " + ex.ToString());
|
|
}
|
|
|
|
}//bind
|
|
|
|
private void unBind()
|
|
{
|
|
if (connectionState== ConnectionStates.SMPP_BINDED)
|
|
{
|
|
try
|
|
{
|
|
byte[] _PDU = new byte[16];
|
|
|
|
Tools.CopyIntToArray(16, _PDU, 0);
|
|
|
|
Tools.CopyIntToArray(0x00000006, _PDU, 4);
|
|
|
|
Tools.CopyIntToArray(smscArray.currentSMSC.SequenceNumber, _PDU, 12);
|
|
|
|
logMessage(LogLevels.LogSteps, "Unbind sent.");
|
|
connectionState= ConnectionStates.SMPP_UNBIND_SENT;
|
|
|
|
Send(_PDU, 16);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "unBind | " + ex.ToString());
|
|
}
|
|
}
|
|
|
|
}//unBind
|
|
|
|
|
|
private void processSubmitSmResp(SubmitSmRespEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
undeliveredMessages--;
|
|
|
|
if (OnSubmitSmResp != null)
|
|
{
|
|
OnSubmitSmResp(e);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "processSubmitSmResp | " + ex.ToString());
|
|
}
|
|
|
|
}//processSubmitSmResp
|
|
|
|
private void processDeliverSm(DeliverSmEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
if (OnDeliverSm != null)
|
|
{
|
|
OnDeliverSm(e);
|
|
}
|
|
else
|
|
sendDeliverSmResp(e.SequenceNumber, StatusCodes.ESME_ROK);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "processDeliverSm | " + ex.ToString());
|
|
}
|
|
}//processDeliverSm
|
|
|
|
private void processLog(LogEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
if (OnLog != null)
|
|
{
|
|
OnLog(e);
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
|
|
}//processLog
|
|
|
|
private void logMessage(int logLevel, string pMessage)
|
|
{
|
|
try
|
|
{
|
|
if (this.writeLog)
|
|
{
|
|
bool isError = false;
|
|
if ((logLevel & LogLevels.LogErrors) == LogLevels.LogErrors)
|
|
isError = true;
|
|
else if ((logLevel & LogLevels.LogExceptions) == LogLevels.LogExceptions)
|
|
isError = true;
|
|
|
|
Notification.AddEventToLog(String.Format("{0} ({1})", pMessage, logLevel.ToString()), isError, false);
|
|
}
|
|
if ((this.LogLevel & logLevel) > 0)
|
|
{
|
|
LogEventArgs evArg = new LogEventArgs(pMessage);
|
|
processLog(evArg);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// DO NOT USE LOG INSIDE LOG FUNCTION !!! logMessage(LogLevels.LogExceptions, "logMessage | " +ex.ToString());
|
|
}
|
|
}//logMessage
|
|
|
|
private void connectCallback(IAsyncResult ar)
|
|
{
|
|
try
|
|
{
|
|
// Retrieve the socket from the state object.
|
|
Socket client = (Socket)ar.AsyncState;
|
|
|
|
// Complete the connection.
|
|
client.EndConnect(ar);
|
|
clientSocket = client;
|
|
clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, 1);
|
|
connectionState= ConnectionStates.SMPP_SOCKET_CONNECTED;
|
|
logMessage(LogLevels.LogSteps, "Connected");
|
|
lastSeenConnected = DateTime.Now;
|
|
bind();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "connectCallback | " + ex.ToString());
|
|
tryToReconnect();
|
|
}
|
|
}//connectCallback
|
|
|
|
|
|
private void tryToReconnect()
|
|
{
|
|
try
|
|
{
|
|
disconnectSocket();
|
|
Thread.Sleep(reconnectTimeout);
|
|
if (mustBeConnected)
|
|
{
|
|
smscArray.NextSMSC();
|
|
connectToSMSC();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "tryToReconnect | " + ex.ToString());
|
|
}
|
|
|
|
}//tryToReconnect
|
|
|
|
private void receiveCallback(IAsyncResult ar)
|
|
{
|
|
try
|
|
{
|
|
int _command_length;
|
|
uint _command_id;
|
|
int _command_status;
|
|
int _sequence_number;
|
|
int _body_length;
|
|
byte[] _PDU_body = new byte[0];
|
|
byte[] _RESPONSE_PDU = new byte[KernelParameters.MaxPduSize];
|
|
int i, x;
|
|
bool _exit_flag;
|
|
|
|
// Retrieve the state object and the client socket
|
|
// from the async state object.
|
|
StateObject state = (StateObject)ar.AsyncState;
|
|
Socket client = state.workSocket;
|
|
// Read data from the remote device.
|
|
int bytesRead = client.EndReceive(ar);
|
|
logMessage(LogLevels.LogSteps, "Received " + Tools.ConvertIntToHexString(bytesRead) + " bytes");
|
|
System.Diagnostics.Debug.WriteLine(Tools.ConvertArrayToHexString(state.buffer, bytesRead));
|
|
if (bytesRead > 0)
|
|
{
|
|
// There might be more data, so store the data received so far.
|
|
if ((LogLevel & LogLevels.LogPdu) > 0)
|
|
logMessage(LogLevels.LogPdu, "Received Binary Data " + Tools.ConvertArrayToHexString(state.buffer, bytesRead));
|
|
//////////////////////////////
|
|
/// Begin processing SMPP messages
|
|
///
|
|
mLen = mPos + bytesRead;
|
|
if (mLen > KernelParameters.MaxBufferSize)
|
|
{
|
|
mPos = 0;
|
|
mLen = 0;
|
|
mbResponse = new byte[KernelParameters.MaxBufferSize];
|
|
}
|
|
else
|
|
{
|
|
Array.Copy(state.buffer, 0, mbResponse, mPos, bytesRead);
|
|
mPos = mLen;
|
|
_exit_flag = false;
|
|
x = 0;
|
|
while (((mLen - x) >= 16) && (_exit_flag == false))
|
|
{
|
|
_command_length = mbResponse[x + 0];
|
|
for (i = x + 1; i < x + 4; i++)
|
|
{
|
|
_command_length <<= 8;
|
|
_command_length = _command_length | mbResponse[i];
|
|
}
|
|
|
|
_command_id = mbResponse[x + 4];
|
|
for (i = x + 5; i < x + 8; i++)
|
|
{
|
|
_command_id <<= 8;
|
|
_command_id = _command_id | mbResponse[i];
|
|
}
|
|
|
|
_command_status = mbResponse[x + 8];
|
|
for (i = x + 9; i < x + 12; i++)
|
|
{
|
|
_command_status <<= 8;
|
|
_command_status = _command_status | mbResponse[i];
|
|
}
|
|
|
|
_sequence_number = mbResponse[x + 12];
|
|
for (i = x + 13; i < x + 16; i++)
|
|
{
|
|
_sequence_number <<= 8;
|
|
_sequence_number = _sequence_number | mbResponse[i];
|
|
}
|
|
if ((_command_length <= (mLen - x)) && (_command_length >= 16))
|
|
{
|
|
if (_command_length == 16)
|
|
_body_length = 0;
|
|
else
|
|
{
|
|
_body_length = _command_length - 16;
|
|
_PDU_body = new byte[_body_length];
|
|
Array.Copy(mbResponse, x + 16, _PDU_body, 0, _body_length);
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
///SMPP Command parsing
|
|
System.Diagnostics.Debug.WriteLine("Command_id {0}", _command_id.ToString());
|
|
switch (_command_id)
|
|
{
|
|
case 0x80000009:
|
|
logMessage(LogLevels.LogSteps, "Bind_Transiver_Resp");
|
|
|
|
if (connectionState== ConnectionStates.SMPP_BIND_SENT)
|
|
{
|
|
if (_command_status == 0)
|
|
{
|
|
connectionState= ConnectionStates.SMPP_BINDED;
|
|
logMessage(LogLevels.LogSteps, "SMPP Binded");
|
|
}
|
|
else
|
|
{
|
|
logMessage(LogLevels.LogSteps | LogLevels.LogErrors, "SMPP BIND ERROR : " + Tools.ConvertIntToHexString(_command_status));
|
|
disconnect(client);
|
|
tryToReconnect();
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
logMessage(LogLevels.LogSteps | LogLevels.LogWarnings, "ERROR #3011 : Unexpected Bind_Transiver_Resp");
|
|
}
|
|
break;
|
|
case 0x80000004:
|
|
logMessage(LogLevels.LogSteps, "Ïîëó÷åí ïàêåò: Submit_Sm_Resp");
|
|
logMessage(LogLevels.LogSteps, "Ñòàòóñ êîìàíäû: " + _command_status.ToString("X8"));
|
|
SubmitSmRespEventArgs evArg = new SubmitSmRespEventArgs(_sequence_number, _command_status, Tools.ConvertArrayToString(_PDU_body, _body_length - 1));
|
|
logMessage(LogLevels.LogSteps, "Ñîäåðæàíèå: " + Tools.ConvertArrayToHexString(_PDU_body, _PDU_body.Length));
|
|
logMessage(LogLevels.LogSteps, "Ñîäåðæàíèå: " + Tools.ConvertArrayToString(_PDU_body, _PDU_body.Length));
|
|
processSubmitSmResp(evArg);
|
|
break;
|
|
case 0x80000103:
|
|
logMessage(LogLevels.LogSteps, "Data_Sm_Resp");
|
|
evArg = new SubmitSmRespEventArgs(_sequence_number, _command_status, Tools.ConvertArrayToString(_PDU_body, _body_length - 1));
|
|
processSubmitSmResp(evArg);
|
|
break;
|
|
case 0x80000015:
|
|
logMessage(LogLevels.LogSteps, "Enquire_Link_Resp");
|
|
enquireLinkResponseTime = DateTime.Now;
|
|
break;
|
|
case 0x00000015:
|
|
logMessage(LogLevels.LogSteps, "Enquire_Link");
|
|
sendEnquireLinkResp(_sequence_number);
|
|
break;
|
|
case 0x80000006:
|
|
logMessage(LogLevels.LogSteps, "Unbind_Resp");
|
|
connectionState= ConnectionStates.SMPP_UNBINDED;
|
|
disconnect(client);
|
|
break;
|
|
case 0x00000005:
|
|
logMessage(LogLevels.LogSteps, "Deliver_Sm");
|
|
decodeAndProcessDeliverSm(_sequence_number, _PDU_body, _body_length);
|
|
break;
|
|
case 0x00000103:
|
|
logMessage(LogLevels.LogSteps, "Data_Sm");
|
|
decodeAndProcessDataSm(_sequence_number, _PDU_body, _body_length);
|
|
break;
|
|
default:
|
|
sendGenericNack(_sequence_number, StatusCodes.ESME_RINVCMDID);
|
|
logMessage(LogLevels.LogSteps | LogLevels.LogWarnings, "Unknown SMPP PDU type" + Tools.ConvertUIntToHexString(_command_id));
|
|
break;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
///END SMPP Command parsing
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
if (_command_length == (mLen - x))
|
|
{
|
|
mLen = 0;
|
|
mPos = 0;
|
|
x = 0;
|
|
_exit_flag = true;
|
|
}
|
|
else
|
|
{
|
|
x += _command_length;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sendGenericNack(_sequence_number, StatusCodes.ESME_RINVMSGLEN);
|
|
mLen -= x;
|
|
mPos = mLen;
|
|
Array.Copy(mbResponse, x, mbResponse, 0, mLen);
|
|
_exit_flag = true;
|
|
logMessage(LogLevels.LogSteps | LogLevels.LogWarnings, "Invalid PDU Length");
|
|
}
|
|
if (x < mLen)
|
|
logMessage(LogLevels.LogPdu, "NEXT PDU STEP IN POS " + Convert.ToString(x) + " FROM " + Convert.ToString(mLen));
|
|
}
|
|
}
|
|
//////////////////////////////
|
|
/// End processing SMPP messages
|
|
// Get the rest of the data.
|
|
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
|
|
new AsyncCallback(receiveCallback), state);
|
|
}
|
|
else
|
|
{
|
|
logMessage(LogLevels.LogSteps | LogLevels.LogWarnings, "Incoming network buffer from SMSC is empty.");
|
|
/* if (client.Poll(0,SelectMode.SelectError)&&client.Poll(0,SelectMode.SelectRead)&&client.Poll(0,SelectMode.SelectWrite))
|
|
{
|
|
logMessage(LogLevels.LogSteps|LogLevels.LogExceptions, "Socket Error");
|
|
unBind();
|
|
}
|
|
*/
|
|
tryToReconnect();
|
|
}
|
|
}
|
|
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "receiveCallback | " + ex.ToString());
|
|
unBind();
|
|
}
|
|
|
|
}//receiveCallback
|
|
|
|
private void initClientParameters()
|
|
{
|
|
mbResponse = new byte[KernelParameters.MaxBufferSize];
|
|
mPos = 0;
|
|
mLen = 0;
|
|
|
|
enquireLinkResponseTime = DateTime.Now;
|
|
|
|
undeliveredMessages = 0;
|
|
}//initClientParameters
|
|
|
|
private void decodeAndProcessDeliverSm(int sequence_number, byte[] _body, int _length)
|
|
{
|
|
if (_length < 17)
|
|
{
|
|
sendDeliverSmResp(sequence_number, StatusCodes.ESME_RINVCMDLEN);
|
|
return;
|
|
}
|
|
try
|
|
{
|
|
bool isDeliveryReceipt = false;
|
|
bool isUdhiSet = false;
|
|
byte _source_addr_ton, _source_addr_npi, _dest_addr_ton, _dest_addr_npi;
|
|
byte _priority_flag, _data_coding, _esm_class;
|
|
byte[] _source_addr = new byte[21];
|
|
byte[] _dest_addr = new byte[21];
|
|
byte saLength, daLength;
|
|
byte[] _short_message = new byte[0];
|
|
int _sm_length;
|
|
int pos;
|
|
|
|
/////////////////////////////////////
|
|
/// Message Delivery Params
|
|
///
|
|
byte[] _receipted_message_id = new byte[254];
|
|
byte _receipted_message_id_len = 0;
|
|
byte _message_state = 0;
|
|
Int16 sar_msg_ref_num = 0;
|
|
byte sar_total_segments = 0;
|
|
byte sar_segment_seqnum = 0;
|
|
|
|
pos = 0;
|
|
while ((pos < 5) && (_body[pos] != 0x00))
|
|
pos++;
|
|
if (_body[pos] != 0x00)
|
|
{
|
|
sendDeliverSmResp(sequence_number, StatusCodes.ESME_RUNKNOWNERR);
|
|
logMessage(LogLevels.LogExceptions, "decodeAndProcessDeliverSm returned UNKNOWNERR on 0x01");
|
|
return;
|
|
}
|
|
_source_addr_ton = _body[++pos];
|
|
_source_addr_npi = _body[++pos];
|
|
pos++;
|
|
saLength = 0;
|
|
while ((saLength < 20) && (_body[pos] != 0x00))
|
|
{
|
|
_source_addr[saLength] = _body[pos];
|
|
pos++;
|
|
saLength++;
|
|
}
|
|
if (_body[pos] != 0x00)
|
|
{
|
|
sendDeliverSmResp(sequence_number, StatusCodes.ESME_RUNKNOWNERR);
|
|
logMessage(LogLevels.LogExceptions, "decodeAndProcessDeliverSm returned UNKNOWNERR on 0x02");
|
|
return;
|
|
}
|
|
_dest_addr_ton = _body[++pos];
|
|
_dest_addr_npi = _body[++pos];
|
|
pos++;
|
|
daLength = 0;
|
|
while ((daLength < 20) && (_body[pos] != 0x00))
|
|
{
|
|
_dest_addr[daLength] = _body[pos];
|
|
pos++;
|
|
daLength++;
|
|
}
|
|
if (_body[pos] != 0x00)
|
|
{
|
|
sendDeliverSmResp(sequence_number, StatusCodes.ESME_RUNKNOWNERR);
|
|
logMessage(LogLevels.LogExceptions, "decodeAndProcessDeliverSm returned UNKNOWNERR on 0x03");
|
|
return;
|
|
}
|
|
_esm_class = _body[++pos];
|
|
switch (_esm_class)
|
|
{
|
|
case 0x00:
|
|
break;
|
|
case 0x04:
|
|
logMessage(LogLevels.LogSteps, "Delivery Receipt Received");
|
|
isDeliveryReceipt = true;
|
|
break;
|
|
case 0x40:
|
|
logMessage(LogLevels.LogSteps, "UDHI Indicator set");
|
|
isUdhiSet = true;
|
|
break;
|
|
default:
|
|
logMessage(LogLevels.LogSteps | LogLevels.LogWarnings, "Unknown esm_class for DELIVER_SM : " + Tools.GetHexFromByte(_esm_class));
|
|
break;
|
|
}
|
|
pos += 1;
|
|
_priority_flag = _body[++pos];
|
|
pos += 4;
|
|
_data_coding = _body[++pos];
|
|
pos += 1;
|
|
_sm_length = _body[++pos];
|
|
pos += 1;
|
|
if (_sm_length > 0)
|
|
{
|
|
_short_message = new byte[_sm_length];
|
|
Array.Copy(_body, pos, _short_message, 0, _sm_length);
|
|
}
|
|
if ((isDeliveryReceipt) || (isUdhiSet))
|
|
{
|
|
int _par_tag, _par_tag_length;
|
|
bool exit = false;
|
|
if (_sm_length > 0)
|
|
{
|
|
pos += _sm_length;
|
|
}
|
|
while ((pos < _length) && (exit == false))
|
|
{
|
|
if (Tools.Get2ByteIntFromArray(_body, pos, _length, out _par_tag) == false)
|
|
{
|
|
exit = true;
|
|
break;
|
|
}
|
|
pos += 2;
|
|
if (Tools.Get2ByteIntFromArray(_body, pos, _length, out _par_tag_length) == false)
|
|
{
|
|
exit = true;
|
|
break;
|
|
}
|
|
pos += 2;
|
|
switch (_par_tag)
|
|
{
|
|
case 0x020C:
|
|
if (((pos + _par_tag_length - 1) <= _length) && (_par_tag_length == 2))
|
|
{
|
|
byte[] temp = new byte[_par_tag_length];
|
|
Array.Copy(_body, pos, temp, 0, _par_tag_length);
|
|
pos += _par_tag_length;
|
|
sar_msg_ref_num = BitConverter.ToInt16(temp, 0);
|
|
logMessage(LogLevels.LogSteps, "sar_msg_ref_num : " + sar_msg_ref_num);
|
|
}
|
|
else
|
|
exit = true;
|
|
|
|
break;
|
|
case 0x020E:
|
|
if ((pos <= _length) && (_par_tag_length == 1))
|
|
{
|
|
sar_total_segments = _body[pos];
|
|
logMessage(LogLevels.LogSteps, "sar_total_segments : " + Convert.ToString(sar_total_segments));
|
|
pos++;
|
|
}
|
|
else
|
|
exit = true;
|
|
|
|
break;
|
|
case 0x020F:
|
|
if ((pos <= _length) && (_par_tag_length == 1))
|
|
{
|
|
sar_segment_seqnum = _body[pos];
|
|
logMessage(LogLevels.LogSteps, "sar_segment_seqnum : " + Convert.ToString(sar_segment_seqnum));
|
|
pos++;
|
|
}
|
|
else
|
|
exit = true;
|
|
|
|
break;
|
|
case 0x0427:
|
|
if ((pos <= _length) && (_par_tag_length == 1))
|
|
{
|
|
_message_state = _body[pos];
|
|
logMessage(LogLevels.LogSteps, "Message state : " + Convert.ToString(_message_state));
|
|
pos++;
|
|
}
|
|
else
|
|
exit = true;
|
|
|
|
break;
|
|
case 0x001E:
|
|
if ((pos + _par_tag_length - 1) <= _length)
|
|
{
|
|
_receipted_message_id = new byte[_par_tag_length];
|
|
Array.Copy(_body, pos, _receipted_message_id, 0, _par_tag_length);
|
|
_receipted_message_id_len = Convert.ToByte(_par_tag_length);
|
|
pos += _par_tag_length;
|
|
logMessage(LogLevels.LogSteps, "Delivered message id : " + Tools.ConvertArrayToString(_receipted_message_id, _receipted_message_id_len - 1));
|
|
}
|
|
else
|
|
exit = true;
|
|
break;
|
|
default:
|
|
if ((pos + _par_tag_length - 1) <= _length)
|
|
pos += _par_tag_length;
|
|
else
|
|
exit = true;
|
|
logMessage(LogLevels.LogDebug, "_par_tag : " + Convert.ToString(_par_tag));
|
|
logMessage(LogLevels.LogDebug, "_par_tag_length : " + Convert.ToString(_par_tag_length));
|
|
break;
|
|
|
|
}
|
|
}
|
|
logMessage(LogLevels.LogDebug, "Delivery Receipt Processing Exit value - " + Convert.ToString(exit));
|
|
if (exit)
|
|
isDeliveryReceipt = false;
|
|
}
|
|
|
|
if ((sar_msg_ref_num > 0) && ((sar_total_segments > 0) && ((sar_segment_seqnum > 0) && (isUdhiSet))))
|
|
{
|
|
lock (sarMessages.SyncRoot)
|
|
{
|
|
SortedList tArr = new SortedList();
|
|
if (sarMessages.ContainsKey(sar_msg_ref_num))
|
|
{
|
|
tArr = (SortedList)sarMessages[sar_msg_ref_num];
|
|
if (tArr.ContainsKey(sar_segment_seqnum))
|
|
tArr[sar_segment_seqnum] = _short_message;
|
|
else
|
|
tArr.Add(sar_segment_seqnum, _short_message);
|
|
bool isFull = true;
|
|
byte i;
|
|
for (i = 1; i <= sar_total_segments; i++)
|
|
{
|
|
if (!tArr.ContainsKey(i))
|
|
{
|
|
isFull = false;
|
|
break;
|
|
}//if
|
|
}//for
|
|
if (!isFull)
|
|
{
|
|
sarMessages[sar_msg_ref_num] = tArr;
|
|
sendDeliverSmResp(sequence_number, StatusCodes.ESME_ROK);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
_sm_length = 0;
|
|
for (i = 1; i <= sar_total_segments; i++)
|
|
{
|
|
_sm_length += ((byte[])tArr[i]).Length;
|
|
}
|
|
_short_message = new byte[_sm_length + 100];
|
|
_sm_length = 0;
|
|
for (i = 1; i <= sar_total_segments; i++)
|
|
{
|
|
Array.Copy(((byte[])tArr[i]), 0, _short_message, _sm_length, ((byte[])tArr[i]).Length);
|
|
_sm_length += ((byte[])tArr[i]).Length;
|
|
}
|
|
sarMessages.Remove(sar_msg_ref_num);
|
|
}
|
|
}//if
|
|
else
|
|
{
|
|
tArr.Add(sar_segment_seqnum, _short_message);
|
|
sarMessages.Add(sar_msg_ref_num, tArr);
|
|
sendDeliverSmResp(sequence_number, StatusCodes.ESME_ROK);
|
|
return;
|
|
}
|
|
}//lock
|
|
}
|
|
string to;
|
|
string from;
|
|
string textString;
|
|
|
|
string hexString = "";
|
|
|
|
byte messageState = 0;
|
|
string receiptedMessageID = "";
|
|
|
|
to = Encoding.ASCII.GetString(_dest_addr, 0, daLength);
|
|
from = Encoding.ASCII.GetString(_source_addr, 0, saLength);
|
|
if (_data_coding == 8) //USC2
|
|
textString = Encoding.BigEndianUnicode.GetString(_short_message, 0, _sm_length);
|
|
else
|
|
textString = Encoding.UTF8.GetString(_short_message, 0, _sm_length);
|
|
hexString = Tools.ConvertArrayToHexString(_short_message, _sm_length);
|
|
|
|
if (isDeliveryReceipt)
|
|
{
|
|
isDeliveryReceipt = true;
|
|
messageState = _message_state;
|
|
receiptedMessageID = Encoding.ASCII.GetString(_receipted_message_id, 0, _receipted_message_id_len - 1); ;
|
|
}
|
|
|
|
DeliverSmEventArgs evArg = new DeliverSmEventArgs(sequence_number, to, from, textString, hexString, _data_coding, _esm_class, isDeliveryReceipt, messageState, receiptedMessageID);
|
|
processDeliverSm(evArg);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "decodeAndProcessDeliverSm | " + ex.ToString());
|
|
sendDeliverSmResp(sequence_number, StatusCodes.ESME_RUNKNOWNERR);
|
|
}
|
|
|
|
}//decodeAndProcessDeliverSm
|
|
|
|
private void decodeAndProcessDataSm(int sequence_number, byte[] _body, int _length)
|
|
{
|
|
if (_length < 17)
|
|
{
|
|
sendDeliverSmResp(sequence_number, StatusCodes.ESME_RINVCMDLEN);
|
|
return;
|
|
}
|
|
try
|
|
{
|
|
bool isDeliveryReceipt = false;
|
|
byte _source_addr_ton, _source_addr_npi, _dest_addr_ton, _dest_addr_npi;
|
|
byte _priority_flag, _data_coding, _esm_class;
|
|
byte[] _source_addr = new byte[21];
|
|
byte[] _dest_addr = new byte[21];
|
|
byte saLength, daLength;
|
|
byte[] _short_message = new byte[254];
|
|
int pos;
|
|
|
|
/////////////////////////////////////
|
|
/// Message Delivery Params
|
|
///
|
|
byte[] _receipted_message_id = new byte[254];
|
|
byte _receipted_message_id_len = 0;
|
|
byte _message_state = 0;
|
|
|
|
|
|
pos = 0;
|
|
while ((pos < 5) && (_body[pos] != 0x00))
|
|
pos++;
|
|
if (_body[pos] != 0x00)
|
|
{
|
|
sendDeliverSmResp(sequence_number, StatusCodes.ESME_RUNKNOWNERR);
|
|
logMessage(LogLevels.LogExceptions, "decodeAndProcessDeliverSm returned UNKNOWNERR on 0x04");
|
|
return;
|
|
}
|
|
_source_addr_ton = _body[++pos];
|
|
_source_addr_npi = _body[++pos];
|
|
pos++;
|
|
saLength = 0;
|
|
while ((saLength < 20) && (_body[pos] != 0x00))
|
|
{
|
|
_source_addr[saLength] = _body[pos];
|
|
pos++;
|
|
saLength++;
|
|
}
|
|
if (_body[pos] != 0x00)
|
|
{
|
|
sendDeliverSmResp(sequence_number, StatusCodes.ESME_RUNKNOWNERR);
|
|
logMessage(LogLevels.LogExceptions, "decodeAndProcessDeliverSm returned UNKNOWNERR on 0x05");
|
|
return;
|
|
}
|
|
_dest_addr_ton = _body[++pos];
|
|
_dest_addr_npi = _body[++pos];
|
|
pos++;
|
|
daLength = 0;
|
|
while ((daLength < 20) && (_body[pos] != 0x00))
|
|
{
|
|
_dest_addr[daLength] = _body[pos];
|
|
pos++;
|
|
daLength++;
|
|
}
|
|
if (_body[pos] != 0x00)
|
|
{
|
|
sendDeliverSmResp(sequence_number, StatusCodes.ESME_RUNKNOWNERR);
|
|
logMessage(LogLevels.LogExceptions, "decodeAndProcessDeliverSm returned UNKNOWNERR on 0x06");
|
|
return;
|
|
}
|
|
_esm_class = _body[++pos];
|
|
switch (_esm_class)
|
|
{
|
|
case 0x00:
|
|
break;
|
|
case 0x04:
|
|
logMessage(LogLevels.LogSteps, "Delivery Receipt Received");
|
|
isDeliveryReceipt = true;
|
|
break;
|
|
default:
|
|
logMessage(LogLevels.LogSteps | LogLevels.LogWarnings, "Unknown esm_class for DATA_SM : " + Tools.GetHexFromByte(_esm_class));
|
|
break;
|
|
}
|
|
pos += 1;
|
|
_priority_flag = _body[++pos];
|
|
pos += 4;
|
|
_data_coding = _body[++pos];
|
|
pos += 1;
|
|
if (isDeliveryReceipt)
|
|
{
|
|
int _par_tag, _par_tag_length;
|
|
bool exit = false;
|
|
while ((pos < _length) && (exit == false))
|
|
{
|
|
if (Tools.Get2ByteIntFromArray(_body, pos, _length, out _par_tag) == false)
|
|
{
|
|
exit = true;
|
|
break;
|
|
}
|
|
pos += 2;
|
|
if (Tools.Get2ByteIntFromArray(_body, pos, _length, out _par_tag_length) == false)
|
|
{
|
|
exit = true;
|
|
break;
|
|
}
|
|
pos += 2;
|
|
switch (_par_tag)
|
|
{
|
|
case 0x0427:
|
|
if ((pos <= _length) && (_par_tag_length == 1))
|
|
{
|
|
_message_state = _body[pos];
|
|
logMessage(LogLevels.LogSteps, "Message state : " + Convert.ToString(_message_state));
|
|
pos++;
|
|
}
|
|
else
|
|
exit = true;
|
|
|
|
break;
|
|
case 0x001E:
|
|
if ((pos + _par_tag_length - 1) <= _length)
|
|
{
|
|
_receipted_message_id = new byte[_par_tag_length];
|
|
Array.Copy(_body, pos, _receipted_message_id, 0, _par_tag_length);
|
|
_receipted_message_id_len = Convert.ToByte(_par_tag_length);
|
|
pos += _par_tag_length;
|
|
logMessage(LogLevels.LogSteps, "Delivered message id : " + Tools.ConvertArrayToString(_receipted_message_id, _receipted_message_id_len - 1));
|
|
}
|
|
else
|
|
exit = true;
|
|
break;
|
|
default:
|
|
if ((pos + _par_tag_length - 1) <= _length)
|
|
pos += _par_tag_length;
|
|
else
|
|
exit = true;
|
|
logMessage(LogLevels.LogDebug, "_par_tag : " + Convert.ToString(_par_tag));
|
|
logMessage(LogLevels.LogDebug, "_par_tag_length : " + Convert.ToString(_par_tag_length));
|
|
break;
|
|
|
|
}
|
|
}
|
|
logMessage(LogLevels.LogDebug, "Delivery Receipt Processing Exit value - " + Convert.ToString(exit));
|
|
if (exit)
|
|
isDeliveryReceipt = false;
|
|
}
|
|
|
|
string to;
|
|
string from;
|
|
string textString = "";
|
|
|
|
string hexString = "";
|
|
|
|
byte messageState = 0;
|
|
string receiptedMessageID = "";
|
|
|
|
to = Encoding.ASCII.GetString(_dest_addr, 0, daLength);
|
|
from = Encoding.ASCII.GetString(_source_addr, 0, saLength);
|
|
|
|
if (isDeliveryReceipt)
|
|
{
|
|
isDeliveryReceipt = true;
|
|
messageState = _message_state;
|
|
receiptedMessageID = Encoding.ASCII.GetString(_receipted_message_id, 0, _receipted_message_id_len - 1); ;
|
|
}
|
|
|
|
DeliverSmEventArgs evArg = new DeliverSmEventArgs(sequence_number, to, from, textString, hexString, _data_coding, _esm_class, isDeliveryReceipt, messageState, receiptedMessageID);
|
|
processDeliverSm(evArg);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "decodeAndProcessDeliverSm | " + ex.ToString());
|
|
sendDeliverSmResp(sequence_number, StatusCodes.ESME_RUNKNOWNERR);
|
|
}
|
|
|
|
}//decodeAndProcessDataSm
|
|
|
|
private void checkSystemIntegrity(Object state)
|
|
{
|
|
try
|
|
{
|
|
if (mustBeConnected)
|
|
{
|
|
if (connectionState== ConnectionStates.SMPP_BINDED)
|
|
{
|
|
if (enquireLinkSendTime <= enquireLinkResponseTime)
|
|
{
|
|
enquireLinkSendTime = DateTime.Now;
|
|
sendEnquireLink(smscArray.currentSMSC.SequenceNumber);
|
|
lastSeenConnected = DateTime.Now;
|
|
}
|
|
else
|
|
{
|
|
logMessage(LogLevels.LogSteps | LogLevels.LogErrors, "checkSystemIntegrity | ERROR #9001 - no response to Enquire Link");
|
|
tryToReconnect();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (((TimeSpan)(DateTime.Now - lastSeenConnected)).TotalSeconds > KernelParameters.CanBeDisconnected)
|
|
{
|
|
logMessage(LogLevels.LogSteps | LogLevels.LogErrors, "checkSystemIntegrity | ERROR #9002 - diconnected more than " + Convert.ToString(KernelParameters.CanBeDisconnected) + " seconds");
|
|
lastSeenConnected = DateTime.Now.AddSeconds(KernelParameters.CanBeDisconnected);
|
|
tryToReconnect();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (connectionState== ConnectionStates.SMPP_UNBIND_SENT)
|
|
{
|
|
if (((TimeSpan)(DateTime.Now - lastPacketSentTime)).TotalSeconds > KernelParameters.WaitPacketResponse)
|
|
{
|
|
disconnectSocket();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "checkSystemIntegrity | " + ex.ToString());
|
|
}
|
|
|
|
}//checkSystemIntegrity
|
|
|
|
public void sendDeliverSmResp(int sequence_number, int command_status)
|
|
{
|
|
try
|
|
{
|
|
byte[] _PDU = new byte[17];
|
|
|
|
Tools.CopyIntToArray(17, _PDU, 0);
|
|
|
|
Tools.CopyIntToArray(0x80000005, _PDU, 4);
|
|
|
|
Tools.CopyIntToArray(command_status, _PDU, 8);
|
|
|
|
Tools.CopyIntToArray(sequence_number, _PDU, 12);
|
|
|
|
_PDU[16] = 0;
|
|
|
|
Send(_PDU, 17);
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "sendDeliverSmResp | " + ex.ToString());
|
|
}
|
|
}//sendDeliverSmResp
|
|
|
|
private void sendGenericNack(int sequence_number, int command_status)
|
|
{
|
|
try
|
|
{
|
|
byte[] _PDU = new byte[16];
|
|
|
|
Tools.CopyIntToArray(16, _PDU, 0);
|
|
|
|
Tools.CopyIntToArray(0x80000000, _PDU, 4);
|
|
|
|
Tools.CopyIntToArray(command_status, _PDU, 8);
|
|
|
|
Tools.CopyIntToArray(sequence_number, _PDU, 12);
|
|
|
|
Send(_PDU, 16);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "sendGenericNack | " + ex.ToString());
|
|
}
|
|
|
|
}//sendGenericNack
|
|
|
|
private void sendEnquireLink(int sequence_number)
|
|
{
|
|
try
|
|
{
|
|
byte[] _PDU = new byte[16];
|
|
Tools.CopyIntToArray(16, _PDU, 0);
|
|
|
|
Tools.CopyIntToArray(0x00000015, _PDU, 4);
|
|
|
|
Tools.CopyIntToArray(0x00000000, _PDU, 8);
|
|
|
|
Tools.CopyIntToArray(sequence_number, _PDU, 12);
|
|
|
|
Send(_PDU, 16);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "sendEnquireLink | " + ex.ToString());
|
|
}
|
|
}//sendEnquireLink
|
|
|
|
private void sendEnquireLinkResp(int sequence_number)
|
|
{
|
|
try
|
|
{
|
|
byte[] _PDU = new byte[16];
|
|
Tools.CopyIntToArray(16, _PDU, 0);
|
|
|
|
Tools.CopyIntToArray(0x80000015, _PDU, 4);
|
|
|
|
Tools.CopyIntToArray(0x00000000, _PDU, 8);
|
|
|
|
Tools.CopyIntToArray(sequence_number, _PDU, 12);
|
|
|
|
Send(_PDU, 16);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "sendEnquireLink | " + ex.ToString());
|
|
}
|
|
}//sendEnquireLink
|
|
|
|
private void sendCallback(IAsyncResult ar)
|
|
{
|
|
try
|
|
{
|
|
// Retrieve the socket from the state object.
|
|
Socket client = (Socket)ar.AsyncState;
|
|
|
|
// Complete sending the data to the remote device.
|
|
int bytesSent = client.EndSend(ar);
|
|
logMessage(LogLevels.LogSteps | LogLevels.LogPdu, "Sent " + bytesSent.ToString() + " bytes");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logMessage(LogLevels.LogExceptions, "Send | " + ex.ToString());
|
|
}
|
|
}//Send
|
|
|
|
private byte getAddrTon(string address)
|
|
{
|
|
int i;
|
|
for (i = 0; i < address.Length; i++)
|
|
if (!Char.IsDigit(address, i))
|
|
{
|
|
return AddressTons.Alphanumeric;
|
|
}
|
|
if (address.Length == nationalNumberLength)
|
|
return AddressTons.National;
|
|
if (address.Length > nationalNumberLength)
|
|
return AddressTons.International;
|
|
return AddressTons.Unknown;
|
|
}//getAddrTon
|
|
private byte getAddrNpi(string address)
|
|
{
|
|
int i;
|
|
for (i = 0; i < address.Length; i++)
|
|
if (!Char.IsDigit(address, i))
|
|
{
|
|
return AddressNpis.Unknown;
|
|
}
|
|
return AddressNpis.ISDN;
|
|
}//getAddrTon
|
|
#endregion Private Functions
|
|
|
|
}//SMPPClient
|
|
|
|
|
|
}
|