/// <summary> /// This method sends a data_sm packet synchronously over to the peer. /// </summary> /// <param name="pdu">data_sm packet</param> /// <returns>data_sm response</returns> public data_sm_resp SendData(data_sm pdu) { data_sm_resp response = null; PduSyncronizer sync = AddWaitingPdu(pdu); if (sync != null) { if (IsBound && SendPdu(pdu)) { if (sync.WaitForResponse()) { response = sync.PduResponse as data_sm_resp; if (response == null) { response = new data_sm_resp(pdu.SequenceNumber, sync.PduResponse.Status); } } else { response = new data_sm_resp(pdu.SequenceNumber, StatusCodes.ESME_RINVEXPIRY); } } else { response = new data_sm_resp(pdu.SequenceNumber, StatusCodes.ESME_RDELIVERYFAILURE); } FindAndRemoveWaitingPdu(pdu.SequenceNumber); } else { response = new data_sm_resp(pdu.SequenceNumber, StatusCodes.ESME_RMSGQFUL); } return(response); }
/// <summary> /// This adds a PDU to our waiting list. /// </summary> /// <param name="pdu">PDU</param> /// <returns>True/False</returns> internal PduSyncronizer AddWaitingPdu(SmppPdu pdu) { lock (this.pendingRequests) { if (this.pendingRequests.Count < DefaultPendingRequestLimit) { PduSyncronizer sync = new PduSyncronizer(pdu, ResponseTimeout); this.pendingRequests.Add(pdu.SequenceNumber, sync); return(sync); } } return(null); }
/// <summary> /// This locates and removes a PduSyncronizer. /// </summary> /// <param name="seqNum">Sequence number to locate</param> /// <returns>PduSyncronizer in question</returns> internal PduSyncronizer FindAndRemoveWaitingPdu(int seqNum) { PduSyncronizer sync = null; lock (this.pendingRequests) { if (this.pendingRequests.ContainsKey(seqNum)) { sync = this.pendingRequests[seqNum]; this.pendingRequests.Remove(seqNum); } } return(sync); }
/// <summary> /// This method sends an enquire link /// </summary> /// <returns></returns> public enquire_link_resp EnquireLink() { SmppPdu pdu = new enquire_link(); enquire_link_resp response = null; PduSyncronizer sync = AddWaitingPdu(pdu); if (sync != null) { if (IsBound && SendPdu(pdu)) { if (sync.WaitForResponse()) { response = sync.PduResponse as enquire_link_resp; if (response == null) { response = new enquire_link_resp(pdu.SequenceNumber, sync.PduResponse.Status); } } else { response = new enquire_link_resp(pdu.SequenceNumber, StatusCodes.ESME_RINVEXPIRY); } } else { response = new enquire_link_resp(pdu.SequenceNumber, StatusCodes.ESME_RINVCMDID); } FindAndRemoveWaitingPdu(pdu.SequenceNumber); } else { response = new enquire_link_resp(pdu.SequenceNumber, StatusCodes.ESME_RMSGQFUL); } return(response); }
/// <summary> /// This method is used to unbind our session synchronously. /// </summary> /// <returns>Unbind response PDU</returns> public unbind_resp UnBind() { unbind pdu = new unbind(); unbind_resp response = null; PduSyncronizer sync = AddWaitingPdu(pdu); if (sync != null) { if (IsBound && SendPdu(pdu)) { if (sync.WaitForResponse()) { response = sync.PduResponse as unbind_resp; if (response == null) { response = new unbind_resp(pdu.SequenceNumber, sync.PduResponse.Status); } } else { response = new unbind_resp(pdu.SequenceNumber, StatusCodes.ESME_RINVEXPIRY); } } else { response = new unbind_resp(pdu.SequenceNumber, StatusCodes.ESME_RINVBNDSTS); } FindAndRemoveWaitingPdu(pdu.SequenceNumber); } else { response = new unbind_resp(pdu.SequenceNumber, StatusCodes.ESME_RMSGQFUL); } return(response); }
/// <summary> /// This method is called when data is received from our socket. /// </summary> /// <param name="sender">The socket which sent the data</param> /// <param name="args">Socket data</param> protected virtual void OnReceiveData(object sender, SocketEventArgs args) { SocketClient socket = (SocketClient)sender; ReadEventArgs re = (ReadEventArgs)args; int packetLength = SmppPdu.REQUIRED_SIZE; if (re.Length >= packetLength) { // Get the first DWORD from the buffer; this is the total size of the packet. packetLength = BitConverter.ToInt32(new byte[] { re.Buffer[3], re.Buffer[2], re.Buffer[1], re.Buffer[0] }, 0); if (re.Length >= packetLength) { try { // Have the entire buffer; parse it out. SmppPdu pdu = SmppPdu.Create(new SmppByteStream(re.Buffer)); SmppPduReceivedEventArgs ea = new SmppPduReceivedEventArgs(this, pdu); FireEvent(EventType.PreProcessPdu, ea); PduSyncronizer sync = null; if (pdu is SmppResponse) { if ((sync = FindAndRemoveWaitingPdu(pdu.SequenceNumber)) != null) { ((SmppResponse)pdu).OriginalRequest = (SmppRequest)sync.PduRequest; } else { throw new SmppException("Invalid pdu response received with no pending request: " + pdu.ToString()); } } if (!ea.Handled) { try { ProcessPdu(pdu); } catch (InvalidSmppStateException) { if (pdu.RequiresResponse) { SendPdu(new generic_nack(StatusCodes.ESME_RINVCMDID, pdu.SequenceNumber)); } } } if (sync != null) { sync.PduResponse = pdu; } } catch (PduException pduex) { SmppPdu pdu = (pduex.HasPDU) ? pduex.PDU : null; if (pdu != null && pdu.RequiresResponse) { SendPdu(new generic_nack(StatusCodes.ESME_RINVCMDID, pdu.SequenceNumber)); } FireEvent(EventType.Error, new SmppErrorEventArgs(this, pduex, pdu)); } catch (Exception ex) { socket.Close(true); FireEvent(EventType.SessionDisconnected, new SmppDisconnectEventArgs(this, ex)); } // Reset the buffer re.AppendToBuffer = false; re.NextReadSize = SmppPdu.REQUIRED_SIZE; return; } } // Wait for more data to show up on the socket. re.AppendToBuffer = true; re.NextReadSize = packetLength - re.Length; }