Beispiel #1
0
 /**
  * Confine all interactions with ActiveX controls to this thread
  * Other threads access this thread by adding IMessages to the work_queue
  * and should monitor the http_mailbox for responses
  */
 public void DeviceLoop()
 {
     Console.WriteLine("Starting device thread: " + Thread.CurrentThread.ManagedThreadId);
     this.ReInitDevice();
     while (true)
     {
         var msg = this.work_queue.Take();
         if (msg.type() == "simple")
         {
             this.ProcessUdpMessage(msg.body());
         }
         else if (msg.type() == "emv")
         {
             string result = emv_ax_control.ProcessTransaction(msg.body());
             if (msg.from() == "http")
             {
                 this.http_mailbox.Add(result);
             }
         }
         else if (msg.type() == "pdc")
         {
             string result = pdc_ax_control.ProcessTransaction(msg.body(), 1, null, null);
             if (msg.from() == "http")
             {
                 this.http_mailbox.Add(result);
             }
         }
     }
 }
Beispiel #2
0
        /**
         * Process XML transaction using dsiPDCX
         */
        protected string ProcessEMV(string xml)
        {
            /*
             * Substitute values into the XML request
             * This is so the driver can handle any change
             * in which hardware device is connected as well
             * as so tracking SequenceNo values is not POS'
             * problem.
             */
            xml = xml.Trim(new char[] { '"' });
            xml = xml.Replace("{{SequenceNo}}", SequenceNo());
            if (IsCanadianDeviceType(this.device_identifier))
            {
                // tag name is different in this case;
                // replace placeholder then the open/close tags
                xml = xml.Replace("{{SecureDevice}}", this.device_identifier);
                xml = xml.Replace("SecureDevice", "PadType");
            }
            else
            {
                xml = xml.Replace("{{SecureDevice}}", SecureDeviceToEmvType(this.device_identifier));
            }
            xml = xml.Replace("{{ComPort}}", com_port);
            if (this.verbose_mode > 0)
            {
                Console.WriteLine(xml);
            }
            if (log_xml)
            {
                using (StreamWriter file = new StreamWriter("log.xml", true)) {
                    file.WriteLine(xml);
                }
            }

            string result = emv_ax_control.ProcessTransaction(xml);
            // track SequenceNo values in responses
            XmlDocument doc = new XmlDocument();

            try {
                doc.LoadXml(result);
                XmlNode sequence = doc.SelectSingleNode("RStream/CmdResponse/SequenceNo");
                sequence_no = sequence.Value;
            } catch (Exception ex) {
                if (this.verbose_mode > 0)
                {
                    Console.WriteLine(ex);
                }
            }

            return(result);
        }
Beispiel #3
0
        /**
         * Process XML transaction using dsiPDCX
         * @param xml the request body
         * @param autoReset true if the request requires a reset, false if the request IS a reset
         */
        protected string ProcessEMV(string xml, bool autoReset)
        {
            /*
             * Substitute values into the XML request
             * This is so the driver can handle any change
             * in which hardware device is connected as well
             * as so tracking SequenceNo values is not POS'
             * problem.
             */
            xml = xml.Trim(new char[] { '"' });
            xml = xml.Replace("{{SequenceNo}}", SequenceNo());
            if (IsCanadianDeviceType(this.device_identifier))
            {
                // tag name is different in this case;
                // replace placeholder then the open/close tags
                xml = xml.Replace("{{SecureDevice}}", this.device_identifier);
                xml = xml.Replace("SecureDevice", "PadType");
            }
            else
            {
                xml = xml.Replace("{{SecureDevice}}", SecureDeviceToEmvType(this.device_identifier));
            }
            xml = xml.Replace("{{ComPort}}", com_port);
            if (this.terminalID.Length > 0)
            {
                xml = xml.Replace("{{TerminalID}}", this.terminalID);
            }

            try {
                /**
                 * Extract HostOrIP field and split it on commas
                 * to allow multiple IPs
                 */
                XmlDocument request = new XmlDocument();
                request.LoadXml(xml);
                var    IPs    = request.SelectSingleNode("TStream/Transaction/HostOrIP").InnerXml.Split(new Char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                string result = "";
                foreach (string IP in IPs)
                {
                    // try request with an IP

                    // If this is NOT a pad reset request, check the emv_reset
                    // flag to see if a reset is needed. If so, execute one
                    // and update the flag
                    if (autoReset)
                    {
                        FlaggedReset();
                    }

                    lock (emvLock) {
                        emv_active = true;
                    }

                    request.SelectSingleNode("TStream/Transaction/HostOrIP").InnerXml = IP;
                    result = emv_ax_control.ProcessTransaction(request.OuterXml);

                    lock (emvLock) {
                        emv_active = false;
                        // if this is not a reset command, set the reset needed flag
                        if (autoReset)
                        {
                            emv_reset = true;
                        }
                    }

                    if (enable_xml_log)
                    {
                        using (StreamWriter sw = new StreamWriter(xml_log, true)) {
                            sw.WriteLine(DateTime.Now.ToString() + " (send emv): " + request.OuterXml);
                            sw.WriteLine(DateTime.Now.ToString() + " (recv emv): " + result);
                        }
                    }
                    XmlDocument doc = new XmlDocument();
                    try {
                        doc.LoadXml(result);
                        // track SequenceNo values in responses
                        XmlNode sequence = doc.SelectSingleNode("RStream/CmdResponse/SequenceNo");
                        sequence_no = sequence.InnerXml;
                        XmlNode return_code = doc.SelectSingleNode("RStream/CmdResponse/DSIXReturnCode");
                        XmlNode origin      = doc.SelectSingleNode("RStream/CmdResponse/ResponseOrigin");

                        /**
                         * On anything that is not a local connectivity failure, exit the
                         * loop and return the result without trying any further IPs.
                         */
                        if (origin.InnerXml != "Client" || return_code.InnerXml != "003006")
                        {
                            break;
                        }
                    } catch (Exception ex) {
                        // response was invalid xml
                        this.LogMessage(ex.ToString());
                        // status is unclear so do not attempt
                        // another transaction
                        break;
                    }
                }

                if (autoReset && this.always_reset)
                {
                    FlaggedReset();
                }

                return(result);
            } catch (Exception ex) {
                // request was invalid xml
                this.LogMessage(ex.ToString());
            }

            return("");
        }
Beispiel #4
0
        /**
         * Process XML transaction using dsiPDCX
         * @param xml the request body
         * @param autoReset true if the request requires a reset, false if the request IS a reset
         */
        protected string ProcessEMV(string xml, bool autoReset)
        {
            /*
             * Substitute values into the XML request
             * This is so the driver can handle any change
             * in which hardware device is connected as well
             * as so tracking SequenceNo values is not POS'
             * problem.
             */
            xml = xml.Replace("{{SequenceNo}}", SequenceNo());
            if (IsCanadianDeviceType(this.device_identifier))
            {
                // tag name is different in this case;
                // replace placeholder then the open/close tags
                xml = xml.Replace("{{SecureDevice}}", this.device_identifier);
                xml = xml.Replace("SecureDevice", "PadType");
            }
            else
            {
                xml = xml.Replace("{{SecureDevice}}", SecureDeviceToEmvType(this.device_identifier));
            }
            xml = xml.Replace("{{ComPort}}", com_port);
            if (this.terminalID.Length > 0)
            {
                xml = xml.Replace("{{TerminalID}}", this.terminalID);
            }
            if (this.device_ip.Length > 0)
            {
                xml = xml.Replace("<ComPort>1</ComPort>", "<ComPort>1</ComPort><PinPadIpAddress>" + this.device_ip + "</PinPadIpAddress><PinPadIpPort>12000</PinPadIpPort>");
            }

            try {
                /**
                 * Extract HostOrIP field and split it on commas
                 * to allow multiple IPs
                 */
                XmlDocument request = new XmlDocument();
                request.LoadXml(xml);
                var IPs = request.SelectSingleNode("TStream/Transaction/HostOrIP").InnerXml.Split(new Char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                if (this.reverse_servers)
                {
                    Array.Reverse(IPs);
                }
                string result = "";
                foreach (string IP in IPs)
                {
                    // try request with an IP

                    // If this is NOT a pad reset request, check the emv_reset
                    // flag to see if a reset is needed. If so, execute one
                    // and update the flag
                    if (autoReset)
                    {
                        FlaggedReset();
                    }

                    lock (emvLock) {
                        emv_active = true;
                    }

                    request.SelectSingleNode("TStream/Transaction/HostOrIP").InnerXml = IP;
                    result = emv_ax_control.ProcessTransaction(request.OuterXml);

                    lock (emvLock) {
                        emv_active = false;
                        // if this is not a reset command, set the reset needed flag
                        if (autoReset)
                        {
                            emv_reset = true;
                        }
                    }

                    if (enable_xml_log)
                    {
                        using (StreamWriter sw = new StreamWriter(xml_log, true)) {
                            sw.WriteLine(DateTime.Now.ToString() + " (send emv): " + request.OuterXml);
                            sw.WriteLine(DateTime.Now.ToString() + " (recv emv): " + result);
                        }
                    }
                    XmlDocument doc = new XmlDocument();
                    try {
                        doc.LoadXml(result);
                        // track SequenceNo values in responses
                        XmlNode sequence = doc.SelectSingleNode("RStream/CmdResponse/SequenceNo");
                        sequence_no = sequence.InnerXml;
                        XmlNode return_code = doc.SelectSingleNode("RStream/CmdResponse/DSIXReturnCode");
                        XmlNode origin      = doc.SelectSingleNode("RStream/CmdResponse/ResponseOrigin");

                        /**
                         * On a client/3006 error or server/4003 error keep trying IPs.
                         * Both indicate a network connectivity error that may just be
                         * transient.
                         * 003327 is a Com Port access error. May be transient in some cases.
                         */
                        if (origin.InnerXml == "Client" && return_code.InnerXml == "003006")
                        {
                            this.LogMessage("Retry on client 3006 (epay: " + IP + ")");
                            this.reverse_servers = !this.reverse_servers;
                        }
                        else if (origin.InnerXml == "Client" && return_code.InnerXml == "003327")
                        {
                            this.LogMessage("Retry on client 3006 (COM error)");
                            Thread.Sleep(500);
                            var new_port = this.PortSearch(this.device_identifier);
                            if (new_port != "" && new_port != this.com_port && new_port.All(char.IsNumber))
                            {
                                this.com_port = new_port;
                            }
                        }
                        else if (origin.InnerXml == "Server" && return_code.InnerXml == "004003")
                        {
                            this.LogMessage("Retry on server 4003 (epay: " + IP + ")");
                        }
                        else
                        {
                            break;
                        }
                    } catch (Exception ex) {
                        // response was invalid xml
                        this.LogMessage(ex.ToString());
                        // status is unclear so do not attempt
                        // another transaction
                        break;
                    }
                }

                if (autoReset && this.always_reset)
                {
                    FlaggedReset();
                }

                return(result);
            } catch (Exception ex) {
                // request was invalid xml
                this.LogMessage(ex.ToString());
            }

            return("");
        }
Beispiel #5
0
        /**
         * Process XML transaction using dsiPDCX
         */
        protected string ProcessEMV(string xml)
        {
            /*
             * Substitute values into the XML request
             * This is so the driver can handle any change
             * in which hardware device is connected as well
             * as so tracking SequenceNo values is not POS'
             * problem.
             */
            xml = xml.Trim(new char[] { '"' });
            xml = xml.Replace("{{SequenceNo}}", SequenceNo());
            if (IsCanadianDeviceType(this.device_identifier))
            {
                // tag name is different in this case;
                // replace placeholder then the open/close tags
                xml = xml.Replace("{{SecureDevice}}", this.device_identifier);
                xml = xml.Replace("SecureDevice", "PadType");
            }
            else
            {
                xml = xml.Replace("{{SecureDevice}}", SecureDeviceToEmvType(this.device_identifier));
            }
            xml = xml.Replace("{{ComPort}}", com_port);
            if (this.verbose_mode > 0)
            {
                Console.WriteLine(xml);
            }
            if (log_xml)
            {
                using (StreamWriter file = new StreamWriter("log.xml", true)) {
                    file.WriteLine(xml);
                }
            }

            try {
                /**
                 * Extract HostOrIP field and split it on commas
                 * to allow multiple IPs
                 */
                XmlDocument request = new XmlDocument();
                request.LoadXml(xml);
                var    IPs    = request.SelectSingleNode("TStream/Transaction/HostOrIP").InnerXml.Split(new Char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                string result = "";
                foreach (string IP in IPs)
                {
                    // try request with an IP
                    request.SelectSingleNode("TStream/Transaction/HostOrIP").InnerXml = IP;
                    result = emv_ax_control.ProcessTransaction(request.OuterXml);
                    XmlDocument doc = new XmlDocument();
                    try {
                        doc.LoadXml(result);
                        // track SequenceNo values in responses
                        XmlNode sequence = doc.SelectSingleNode("RStream/CmdResponse/SequenceNo");
                        sequence_no = sequence.InnerXml;
                        XmlNode return_code = doc.SelectSingleNode("RStream/CmdResponse/DSIXReturnCode");
                        XmlNode origin      = doc.SelectSingleNode("RStream/CmdResponse/ResponseOrigin");

                        /**
                         * On anything that is not a local connectivity failure, exit the
                         * loop and return the result without trying any further IPs.
                         */
                        if (origin.InnerXml != "Client" || return_code.InnerXml != "003006")
                        {
                            break;
                        }
                    } catch (Exception ex) {
                        // response was invalid xml
                        if (this.verbose_mode > 0)
                        {
                            Console.WriteLine(ex);
                        }
                        // status is unclear so do not attempt
                        // another transaction
                        break;
                    }
                }

                return(result);
            } catch (Exception ex) {
                // request was invalid xml
                if (this.verbose_mode > 0)
                {
                    Console.WriteLine(ex);
                }
            }

            return("");
        }