<?php

require_once 'SOAP/Base.php';

/**
*  TCP Transport for SOAP
*
* TODO: Everything
*
* @access public
* @package SOAP::Transport::TCP
* @author Shane Hanna <iordy_at_iordy_dot_com>
*/
class SOAP_Transport_TCP extends SOAP_Base
{

    var $headers = array();
    var $timeout = 10;
    var $urlparts = NULL;
    var $url = '';
    var $incoming_payload = '';
    var $_userAgent = SOAP_LIBRARY_NAME;
    var $encoding = SOAP_DEFAULT_ENCODING;
    var $result_encoding = 'UTF-8';
    var $result_content_type;
    
    # socket
    var $socket = '';
    
    /**
    * SOAP_Transport_TCP Constructor
    *
    * @param string $URL    http url to soap endpoint
    *
    * @access public
    */
    function SOAP_Transport_TCP($URL, $encoding=SOAP_DEFAULT_ENCODING)
    {
        echo "SOAP_Transport_TCP\n";
        parent::SOAP_Base('TCP');
        $this->urlparts = @parse_url($URL);
        $this->url = $URL;
        $this->encoding = $encoding;
        
    }
    
    function _socket_ping () {
        
        if (!$this->socket) {
            echo "SOAP_Transport_TCP->_socket_ping(); \n\tconnecting to host: ".$this->url."\n";
            if(!$this->socket = socket_create(AF_INET, SOCK_STREAM, getprotobyname("TCP"))) return 0;
            if(!socket_connect($this->socket, $this->urlparts['host'], $this->urlparts['port'])) return 0;
            @socket_set_timeout($this->socket, $this->timeout);
        } else {
            echo "SOAP_Transport_TCP->_socket_ping();\n\tconnected to host: ".$this->url."\n";
        }
        return 1;
    }
    
    /**
    * send and receive soap data
    *
    * @param string &$msg       outgoing post data
    * @param string $action      SOAP Action header data
    * @param int $timeout  socket timeout, default 0 or off
    *
    * @return string|fault response
    * @access public
    */
    function &send(&$msg,  /*array*/ $options = NULL)
    {
        echo "SOAP_Transport_TCP->send();\n";
        $this->outgoing_payload = &$msg;
        if (!$this->_validateUrl()) {
            return $this->fault;
        }
        
        # timeout
        if (isset($options['timeout'])) 
            $this->timeout = (int)$options['timeout'];
        
        # check for TCP scheme
        if (strcasecmp($this->urlparts['scheme'], 'TCP') == 0) {
            # check connection
            if (!$this->_socket_ping()) return $this->_raiseSoapFault('error on '.$this->url.' reason '.socket_strerror(socket_last_error($this->socket)));
            
            # send message
            if (!socket_write($this->socket, $this->outgoing_payload, strlen($this->outgoing_payload))) {
                return $this->_raiseSoapFault('Error sending data to '.$this->url.' reason '.socket_strerror());
            }
            
            # get message
            while(($buf = socket_read($this->socket, 1)) !== false) {
                if (strlen($buf) > 0) $this->incoming_payload .= $buf;
            }
            
            # return payload or die
            if ($this->incoming_payload) return $this->incoming_payload;
            return $this->_raiseSoapFault("Error reveiving data from ".$this->url);
        }
        
        return $this->_raiseSoapFault('Invalid url scheme '.$this->url);
    }
    
    // private members
    
    /**
    * validate url data passed to constructor
    *
    * @return boolean
    * @access private
    */
    function _validateUrl()
    {
        if ( ! is_array($this->urlparts) ) {
            $this->_raiseSoapFault("Unable to parse URL $url");
            return FALSE;
        }
        if (!isset($this->urlparts['host'])) {
            $this->_raiseSoapFault("No host in URL $url");
            return FALSE;
        }
        if (!isset($this->urlparts['path']) || !$this->urlparts['path'])
            $this->urlparts['path'] = '/';
        return TRUE;
    }

}
?>