Table of Contents

Multiple Client binds to SMPP servers

The SmppClient represents a single session to the SMPP server. When you need to bind to multiple SMPP servers or when you need to establish several sessions to a SMPP server, you have to create several instances of SmppClient class and attach event handler methods to all instances.

public class SmppRouterSample
{
    private readonly List<SmppClient> _sessions = new List<SmppClient>();

    /// <summary>
    /// The SMPP sessions
    /// </summary>
    public IReadOnlyList<SmppClient> Sessions => _sessions;


    /// <summary>
    /// Add new session with SMPP provider
    /// </summary>
    /// <param name="endPoint">The endpoint of the SMPP provider.</param>
    /// <param name="systemId">The System ID for the Bind command.</param>
    /// <param name="password">The Password for the Bind command.</param>
    /// <param name="systemType">The type of ESME system</param>
    public async Task AddSession(EndPoint endPoint, string systemId, string password, string systemType = null)
    {
        SmppClient client = new SmppClient();
        client.ConnectionRecovery = true;
        client.EnquireLinkInterval = TimeSpan.FromSeconds(30);
        client.SystemType = systemType;

        AttachEvents(client);
        await client.RetryUntilConnectedAsync(endPoint, TimeSpan.FromSeconds(5));

        BindResp resp = await client.BindAsync(systemId, password);
        if (resp.Header.Status != CommandStatus.ESME_ROK)
        {
            throw new InvalidOperationException($"Cannot bind to {endPoint}. Bind Status:  {resp.Header.Status} ");
        }

        _sessions.Add(client);
    }

    /// <summary>
    /// Send SubmitSm PDU to the selected session
    /// </summary>
    /// <param name="submitSm">The SUBMIT_SM PDU</param>
    /// <param name="sessionSelector">The function to select a SMPP session.</param>
    /// <returns></returns>
    public Task<SubmitSmResp> SubmitAsync(SubmitSm submitSm, Func<SmppClient,bool> sessionSelector)
    {
        SmppClient client = Sessions.FirstOrDefault(sessionSelector);

        if (client == null)
        {
            throw new InvalidOperationException("The SMPP session is not found for the message");
        }

        return client.SubmitAsync(submitSm);
    }

    
    /// <summary>
    /// Send SubmitSm PDU to the selected session
    /// </summary>
    /// <param name="builder">The SMS builder</param>
    /// <param name="sessionSelector">The function to select a SMPP session.</param>
    public Task<SubmitSmResp[]> SubmitAsync(IBuilder<SubmitSm> builder, Func<SmppClient, bool> sessionSelector)
    {
        SmppClient client = Sessions.FirstOrDefault(sessionSelector);

        if (client == null)
        {
            throw new InvalidOperationException("The SMPP session is not found for the message");
        }

        return client.SubmitAsync(builder);
    }


    private void AttachEvents(SmppClient smppClient)
    {
        smppClient.evDeliverSm += OnDeliverSm;
        smppClient.evDataSm += OnDataSm;
        smppClient.evUnBind += OnUnbind;
    }

    private void DetachEvents(SmppClient smppClient)
    {
        smppClient.evDeliverSm -= OnDeliverSm;
        smppClient.evDataSm -= OnDataSm;
        smppClient.evUnBind -= OnUnbind;
    }

    private void OnDataSm(object sender, DataSm data)
    {
        SmppClient client = (SmppClient)sender;
        Console.WriteLine($"DATA_SM received from the session {client.RemoteEndPoint}/{client.SystemID}");
    }


    private void OnDeliverSm(object sender, DeliverSm deliverSm)
    {
        SmppClient client = (SmppClient)sender;
        
        if (deliverSm.MessageType == MessageTypes.SMSCDeliveryReceipt)
        {
            Console.WriteLine($"Delivery Receipt received from the session {client.RemoteEndPoint}/{client.SystemID}");
        }
        else
        {
            Console.WriteLine($"Incoming SMS received from the session {client.RemoteEndPoint}/{client.SystemID}");
        }
    }

    private void OnUnbind(object sender, UnBind data)
    {
        SmppClient client = (SmppClient)sender;

        Console.WriteLine($"Unbind the session {client.RemoteEndPoint}/{client.SystemID}");

        DetachEvents(client);

        _sessions.Remove(client);
    }
}

The sample class can be used like this code:


SmppRouterSample router = new SmppRouterSample();
await router.AddSession(new DnsEndPoint("smpp.server.net", 7777), "test", "test");


SubmitSmResp[] resp = await router.SubmitAsync(SMS.ForSubmit().From("SERVICE").To("123456789").Text("my message"), c=>c.SystemID == "test");