/***********************************************************************
 * 
 *  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.Net.Sockets;
using Mono.Unix;
using System.IO;
using System.Text;
using sscs.common;
using sscs.verbs;
using sscs.constants;


namespace sscs.communication
{

class UnixIPCChannel : IPCChannel
{
    // Data
    private Socket clientSocket;
    private UnixUserIdentifier userId;

    //Methods

    internal UnixIPCChannel(Socket connectedSocket)
    {
        CSSSLogger.ExecutionTrace(this);
        clientSocket = connectedSocket;
	Mono.Unix.PeerCred cred;
		cred = new Mono.Unix.PeerCred(connectedSocket);

        userId = new UnixUserIdentifier(cred.UserID);
    }

    override internal UserIdentifier GetIPCChannelUserId()
    {
        CSSSLogger.ExecutionTrace(this);
        return userId;
    }

    private UnixIPCChannel()
    { 
        CSSSLogger.ExecutionTrace(this);
    }
    ~UnixIPCChannel()
    {
        CSSSLogger.ExecutionTrace(this);
        clientSocket.Close();    
    }
    override internal int Read(byte[] buf)
    {
        return 0;
    }
    override internal byte[] Read()
    {
        CSSSLogger.ExecutionTrace(this);
        int bytesRecvd = 0;
        try
        {
            byte[] msgIdBytes = new byte[2];
            bytesRecvd = clientSocket.Receive(msgIdBytes);
            if( 0 == bytesRecvd )
            {
                return null;
            } 
            if( bytesRecvd < 0 ) // IPC is fine and Client had some problem
            {
                throw new CommunicationException("Client has not sent data.");
            }

            byte[] msgLenBytes = new byte[4];
            bytesRecvd = clientSocket.Receive(msgLenBytes);
            if( 0 == bytesRecvd )
            {
                return null;
            } 
            if( bytesRecvd < 0 ) // IPC is fine and Client had some problem
            {
                throw new CommunicationException("Client has not sent data.");
            }

            byte[] bufToReturn = null;
            uint msgLen = BitConverter.ToUInt32(msgLenBytes,0);
            if( msgLen > 6 )
            {
                byte[] buf = new byte[msgLen - 6];
 	        bytesRecvd = clientSocket.Receive (buf);
                CSSSLogger.DbgLog("In " + CSSSLogger.GetExecutionPath(this) + " Bytes received is " + bytesRecvd);
                if( 0 == bytesRecvd )
                {
                    return null;
                } 

                if( bytesRecvd < 0 ) // IPC is fine and Client had some problem
                {
                    throw new CommunicationException("Client has not sent data.");
                }

                bufToReturn = new byte[msgLen];
                Array.Copy(msgIdBytes,bufToReturn,2);
                Array.Copy(msgLenBytes,0,bufToReturn,2,4);
                Array.Copy(buf,0,bufToReturn,6,buf.Length);
                return bufToReturn;
            }
            else
            {
                bufToReturn = new byte[6];
                Array.Copy(msgIdBytes,bufToReturn,2);
                Array.Copy(msgLenBytes,0,bufToReturn,2,4);
                return bufToReturn;
            }
        }
        catch(CommunicationException e)
        {
            throw e;
        }
        catch(Exception e)
        {
            CSSSLogger.ExpLog(e.ToString());
            throw new CommunicationException(e.ToString()); 
        }
    }
    override internal int Write(byte[] buf)
    {
        try
        {
            CSSSLogger.ExecutionTrace(this);
            int bytesSent = clientSocket.Send(buf);
            CSSSLogger.DbgLog("In " + CSSSLogger.GetExecutionPath(this) + " - Bytes sent is " + bytesSent);
            return bytesSent; 
        }
        catch(Exception e)
        {
            CSSSLogger.ExpLog(e.ToString());
            return -1;
        }


    }
    override internal void Close()
    {
        CSSSLogger.ExecutionTrace(this);
        clientSocket.Close();
    }
}
}