/***********************************************************************
 * 
 *  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.
 * 
 ***********************************************************************/

#include "sscs_ipc.h"

#ifdef SSCS_WIN32_PLAT_F
#include "windows.h"
#define  XTIER_RPC_PIPE             TEXT("\\\\.\\PIPE\\SS_RPC_PIPE")

// global
int firstReadAfterWrite = 0;
#endif

/* 
 */

#ifdef SSCS_LINUX_PLAT_F
int ipc_unx_create()
{
    int retVal = 0;
    struct sockaddr_un servAddr;
    char path[MAX_SOCKET_PATH_LEN];
    int sockFd = 0; 
    do
    { 
        sockFd = socket(AF_UNIX,SOCK_STREAM,0);
        if( sockFd < 0 )
        {
            retVal = sockFd;
            break;
        }
        memset(&servAddr,0,sizeof(servAddr));
        servAddr.sun_family = AF_UNIX;

        strcpy(servAddr.sun_path,"/tmp/.novellCASA");
        retVal = connect(sockFd,(struct sockaddr*)&servAddr, sizeof(servAddr));
        if(retVal < 0 )
        {
            DMSG(("Connect fails : %s\n",strerror(errno)));
            DMSG(("Closing socket : %d\n",sockFd));
            close(sockFd);
            break;
        }
        else
            retVal = sockFd;
    }while(0);
    return retVal;
}

#else

void * ipc_win_create()
{

//#ifdef SSCS_WIN32_PLAT_F
	// connect to the named Pipe
	HANDLE hPipe = NULL;
	int rcode;
	DWORD mode = PIPE_READMODE_MESSAGE;

	hPipe = CreateFile(
		XTIER_RPC_PIPE, 
		GENERIC_READ | GENERIC_WRITE, 
		0, 
		NULL, //null, 
		OPEN_EXISTING, 
		0, 
		0);

	if (hPipe == INVALID_HANDLE_VALUE)
	{
		rcode = GetLastError();		
		return 0;
	}

	return hPipe;	
}

#endif	

#ifdef SSCS_LINUX_PLAT_F
int ipc_unx_write(int fd, Byte *pData, int bytes)
{
    int retVal = write(fd,pData,bytes);
    if( retVal < 0 )
    {
        DMSG(("Write returns error : %d - %s\n",retVal, strerror(errno)));
    }
    return retVal;

//#endif
}

#else

int ipc_win_write(HANDLE hPipe, LPCVOID lpBuffer, DWORD bytesToWrite)
{
//#ifdef SSCS_WIN32_PLAT_F
	BOOL rcode;
	int icode;
	DWORD lpBytesWritten = 0;
	//LPCVOID msgLen = malloc(4);

	
	
//	rcode = WaitNamedPipe(
//			XTIER_RPC_PIPE,
//			NMPWAIT_WAIT_FOREVER);



	// the server expects us to first write the number of bytes in the msg we're about to write.
	rcode = WriteFile(
				hPipe,
				(LPCVOID)&bytesToWrite,
				4,
				&lpBytesWritten,
				NULL);
	
	if (!rcode)
	{
		icode = GetLastError();
		return 0;
	}


//	rcode = WaitNamedPipe(
//			XTIER_RPC_PIPE,
//			NMPWAIT_WAIT_FOREVER);

	rcode = WriteFile(
				hPipe,
				lpBuffer,			//LPCVOID lpBuffer,
				bytesToWrite,		//DWORD nNumberOfBytesToWrite,
				&lpBytesWritten,	// LPDWORD lpNumberOfBytesWritten,
				NULL);				//LPOVERLAPPED lpOverlapped

	if (!rcode)
	{
		icode = GetLastError();

	}

	firstReadAfterWrite = 1;
	return lpBytesWritten;
}

#endif

/*
 * 
 */

#ifdef SSCS_LINUX_PLAT_F

int ipc_unx_read(int fd, Byte *pData, int bytes)
{

    int bytesToRead = 0; // Keep track of number of bytes to read
    int bytesRead = 0; // Number of bytes read
    int retVal = 0;

    for(bytesToRead = bytes; bytesToRead;)
    {
        bytesRead = read(fd, pData, bytesToRead);
        if(bytesRead < 0)
        {
            return -1;
        }
        bytesToRead -= bytesRead;
        pData += bytesRead;
    }
    return bytesRead;
}
//#endif


#else

int ipc_win_read(HANDLE hPipe, LPVOID lpBuffer, DWORD numOfBytesToRead)
{
//#ifdef SSCS_WIN32_PLAT_F

	BOOL rcode;
	DWORD numBytesRead = 0;
	LPVOID pMsgLen = malloc(4);
	int icode;
	
	if (firstReadAfterWrite)
	{
		firstReadAfterWrite = 0;

		// server first sends the number of bytes that gets sent.
		rcode =  ReadFile(
					hPipe,					//HANDLE hFile,
					pMsgLen,				//LPVOID lpBuffer,
					4, //numOfBytesToRead,		//DWORD nNumberOfBytesToRead,
					&numBytesRead,			//LPDWORD lpNumberOfBytesRead,
					NULL);					//LPOVERLAPPED lpOverlapped

		if (!rcode)
		{
			icode = GetLastError();
			return 0;
		}
		
	}

	rcode =  ReadFile(
				hPipe,					//HANDLE hFile,
				lpBuffer,				//LPVOID lpBuffer,
				numOfBytesToRead,	//DWORD nNumberOfBytesToRead,
				&numBytesRead,			//LPDWORD lpNumberOfBytesRead,
				NULL);					//LPOVERLAPPED lpOverlapped


	if (pMsgLen)
		free(pMsgLen);

	return numBytesRead;
}
#endif


#ifdef SSCS_LINUX_PLAT_F
int ipc_unx_close(int fd)
{
    return close(fd);

}
#else


int ipc_win_close(HANDLE hPipe)
{
//#ifdef SSCS_WIN32_PLAT_F


	BOOL rcode;
	rcode = DisconnectNamedPipe(hPipe); 
	rcode = CloseHandle(hPipe);
	return 0;
	
}


#endif