Using StreamSocket in external app to talk to OOo

Java, C++, C#, Delphi... - Using the UNO bridges
Post Reply
mangesh
Posts: 26
Joined: Tue Aug 21, 2012 10:48 am

Using StreamSocket in external app to talk to OOo

Post by mangesh »

I have an external application, which connects to OpenOffice.org on a Port 2081. I wish to implement a OOBasic macro, which will connect to the external application and get data from that application. For this I have implemented the osl::AcceptorSocket class which listens to a port ( different than the earlier port). I am trying to connect to it from OOBasic macro. The code in the external application is as follows

Code: Select all

   class MacroListener
    {
    public:
        static const sal_Int32 DEFAULT_PORT;

        MacroListener();
        MacroListener(sal_Int32 port);
        
        ~MacroListener();

        int CreateSocket(sal_Int32 port);

        int ListenOnSocket();

    private:
        
        AcceptorSocket* m_socket;    
        SocketAddr* m_socAddr;
        sal_Int32 m_port;
    };

    const sal_Int32 MacroListener::DEFAULT_PORT = 2042;
    
    MacroListener::MacroListener() : m_port(DEFAULT_PORT)
    {           
        CreateSocket(m_port);
    }

    MacroListener::MacroListener(sal_Int32 port)
    {          
        CreateSocket(m_port);
    }
    
    MacroListener::~MacroListener()
    {            
        delete m_socket;
        delete m_socAddr;
    }     

    int MacroListener::CreateSocket(sal_Int32 port)
    {           
        m_socAddr = new SocketAddr(OUString::createFromAscii("localhost"), port);

        if(!m_socAddr->is())
        {
            printf(" There was an error in creating the SocketAddr \n");
            return 1;
        }

        m_socket = new AcceptorSocket();
               
        if(m_socket == 0)
        {
            printf("error creating  a socket\n");
            return 1;
        }
        
        m_socket->bind(*m_socAddr);
        
        return 0;
    }        

    int MacroListener::ListenOnSocket()
    {
        StreamSocket rConnect;
               
        // number of connections at a time
        m_socket->listen(5);

        int error = 0;
        do
        {
            oslSocketResult result = m_socket->acceptConnection(rConnect);
        
            if(result != oslSocketResult::osl_Socket_Ok)
            {
                oslSocketError error = osl_getLastSocketError(m_socket->getHandle());

                printf(" There was an error in accepting connection \n");
            }
        
            
            // Read data sent by the OOBasic macro 
            {
                sal_Char buffer[256];
                sal_uInt32 size_buffer = 20;
                sal_Int32 n = rConnect.read(buffer, 256); // Returns only after the exception in the macro is thrown

                if(n < 0)
                {
                    printf(" error reading from socket \n");
                    error = 1;
                }

                printf("here is the message: %s \n", buffer);
            }

            // send data back to the OOBasic macro 
            {
                OUString msgBuf = OUString::createFromAscii("I got your message");
               
                sal_Int32 n = rConnect.write("I got your message", 18);

                if(n < 0)
                {
                    printf("error writing to socket");
                    error = 1;
                }
            }
        }
        while(error == 0);

        return 0;
    }
The macro function in OOBasic which connects to it is as follows

Code: Select all

Sub Test2   
   oConnector = createUnoService( "com.sun.star.connection.Connector" )
   oConnection = oConnector.connect("socket,host=localhost,port=2042")   
   
   desc = oConnection.getDescription
      
   cCR = Chr(13)
   cLF = Chr (10) 
   oConnection.write( StringToByteArray(  "Hello World" + cCR + cLF) )
   oConnection.flush()
   aByteArray = Array()
   nBytesRead =  oConnection.read()(aByteArray, 200) //com.sun.star.lang.IllegalArgumentException arguments len differ
   oConnection.close()   
End Sub
My problem is that, I dont return from the call below, immediately after a write (followed by flush) on the connection by the OOBasic macro.

Code: Select all

sal_Int32 n = rConnect.read(buffer, 256)
Also the macro runs through and reports an exception "com.sun.star.lang.IllegalArgumentException arguments len differ" at the line

Code: Select all

 nBytesRead =  oConnection.read()(aByteArray, 200)
I am looking forward to help in making this work. I wish to be able to send and recieve data from the OOBasic macro.
Also I wish to know, how the data should be passed from the OOBasic macro to the external application. Basically how to convert the byte sequence to XInputStream and XOutputStream.

Thanks
Mangesh
OpenOffice3.4.0 Win7 x64.
rudolfo
Volunteer
Posts: 1488
Joined: Wed Mar 19, 2008 11:34 am
Location: Germany

Re: Using StreamSocket in external app to talk to OOo

Post by rudolfo »

Is there any reason why you have to implement this in OOBasic? OOBasic is suitable when you have to loop through the cells in a Calc spreadsheet or if you want to walk through the paragraphs of a Writer document. But anything that is more complicated should be really done with a more advanced scripting language. OpenOffice gives you a choice ... use it! Java, Python, maybe even C#. File handles or descriptors as you have it in sockets or in zip archives require some kind of asynchronous processing or/and at least event handling. Both are not available in Basic. You might be able to achieve something in Basic but it will rather be by workaround then by design. And you will most likely stumble from one workaround to the next. You might have something like an event based reading from a socket descriptor working only to find yourself in a situation where it doesn't work because the reading seems to at random positions in the socket byte stream. Encoding problems, Basic can't handle UTF string in a correct way.

Compared to Microsoft Office Open Office has the choice of different languages for macro writing. This is one of the reasons why OOo Basic is more limited then MS VisualBasic. If MS doesn't invest into Visual Basic they will finally have a monster of an office application without a Macro language. That's more or less a showstopper. If Basic in OpenOffice gets stuck at some release level 2 years back, OpenOffice can still be driven by macros because the end users can simply switch to Python or Java for their macros.
OpenOffice 3.1.1 (2.4.3 until October 2009) and LibreOffice 3.3.2 on Windows 2000, AOO 3.4.1 on Windows 7
There are several macro languages in OOo, but none of them is called Visual Basic or VB(A)! Please call it OOo Basic, Star Basic or simply Basic.
mangesh
Posts: 26
Joined: Tue Aug 21, 2012 10:48 am

Re: Using StreamSocket in external app to talk to OOo

Post by mangesh »

Hi Rudolfo,
Thanks for the inputs. I used OOBasic to quickly check my approach for communicating with an external application. It is now clear that I will have to use a different scripting language. I will update this post with the solution asap.

thanks,
Mangesh
OpenOffice3.4.0 Win7 x64.
Post Reply