/***********************************************************************
 * 
 *  Copyright (C) 2005-2006 Novell, Inc. All Rights Reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; version 2.1
 *  of the License.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, Novell, Inc.
 * 
 *  To contact Novell about this file by physical or electronic mail, 
 *  you may find current contact information at www.novell.com.
 * 
 ***********************************************************************/

using System;
using System.Net;
using System.IO;
using System.Net.Sockets;
using Mono.Unix;

namespace Novell.CASA.MiCasa.Communication
{
    /// <summary>
    /// Summary description for UnixIPCClientChannel.
    /// </summary>
    public class UnixIPCClientChannel : ClientChannel
    {

        private Socket mSocket = null;
        private string socketFileName = "/tmp/.novellCASA";
        private EndPoint sockEndPoint;

        public UnixIPCClientChannel()
        {
        }

        public void Open()
        {
            mSocket = new Socket( AddressFamily.Unix,
                            SocketType.Stream,
                            ProtocolType.IP );

            if (mSocket == null) throw new Exception("could not get socket");
            sockEndPoint = new UnixEndPoint(socketFileName);
            mSocket.Connect(sockEndPoint);	 
        }

        public int Read(byte[] buf)
        {
            buf = Read();

            if (buf != null)
            {
                //Console.WriteLine("Bytes read = " + buf.Length);
                return buf.Length;
            }
            else
                return 0;
        }

        public byte[] Read()
        {
            byte[] returnBuffer = null;
            int bytesRecvd = 0;

            try
            {
                /* We need to read 'msgLen' to know how many bytes to
                 * allocate. 
                 */

                byte[] msgIdBytes = new byte[2];
                bytesRecvd = mSocket.Receive(msgIdBytes);
                if( 0 == bytesRecvd )
                {
                    return null;
                }
                byte[] msgLenBytes = new byte[4];
                bytesRecvd = mSocket.Receive(msgLenBytes);
                if( 0 == bytesRecvd )
                {
                    return null;
                }

                uint msgLen = BitConverter.ToUInt32(msgLenBytes,0);
                if( msgLen > 6 )
                {
                    byte[] buf = new byte[msgLen - 6];
                    bytesRecvd = mSocket.Receive (buf);
                    if( 0 == bytesRecvd )
                    {
                        return null;
                    }

                    returnBuffer = new byte[msgLen];
                    Array.Copy(msgIdBytes,returnBuffer,2);
                    Array.Copy(msgLenBytes,0,returnBuffer,2,4);
                    Array.Copy(buf,0,returnBuffer,6,buf.Length);
                    return returnBuffer;
                }
                else
                {
                    returnBuffer = new byte[6];
                    Array.Copy(msgIdBytes,returnBuffer,2);
                    Array.Copy(msgLenBytes,0,returnBuffer,2,4);
                    return returnBuffer;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
                return null;
            }            
        }
        
        public int Write(byte[] buf)
        {
            try
            {
                mSocket.Send(buf);
                //Console.WriteLine("Bytes written = " + buf.Length);
                return buf.Length;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
                return 0;
            }
        }

        public void Close()
        {
            mSocket.Close();        
        }
    }
}