
//////////////////////////////////////////////////////////////////////
// Rewrite WinSCard hook to SProxy
//////////////////////////////////////////////////////////////////////

LPCSTR	B25_SERVER_IP = "192.168.10.210";

#ifndef SCARD_AUTOALLOCATE
  #define SCARD_AUTOALLOCATE (DWORD)(-1)  //*< see SCardFreeMemory()
#endif

#define TRUE 1
#define FALSE 0

typedef struct {

	BOOL 	(*connect)(void);
	DWORD	(*transmit)(const BYTE *pSendData, const DWORD dwSendSize, BYTE *pRecvData);

} B_CAS_PROXY;

#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>

int 	sockfd;
BOOL Connect(void);
DWORD	TransmitCommand(const BYTE *pSendData, const DWORD dwSendSize, BYTE *pRecvData);

LONG SProxyConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
{
	B_CAS_PROXY *pCasProxy;

	int n = sizeof(B_CAS_PROXY);
	pCasProxy = (B_CAS_PROXY *)malloc(n);

	pCasProxy->connect = Connect;
	pCasProxy->transmit = TransmitCommand;

	if(!pCasProxy->connect()){
		free(pCasProxy);
		phCard = NULL;
		return SCARD_E_READER_UNAVAILABLE;
		}
	*phCard = (LONG)pCasProxy;

	return SCARD_S_SUCCESS;
}

LONG SProxyDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
{
	B_CAS_PROXY *pCasProxy = (B_CAS_PROXY *)(hCard);
	if(pCasProxy) free(pCasProxy);
	close(sockfd);
	return SCARD_S_SUCCESS;
}

LONG SProxyEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
{
	return SCARD_S_SUCCESS;
}

LONG SProxyListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders, LPDWORD pcchReaders)
{
	const char szReaderName[] = "BonCasLink Proxy Card Reader\0";

	if(pcchReaders){
		if((*pcchReaders == SCARD_AUTOALLOCATE) && mszReaders){
			*((LPCSTR *)mszReaders) = szReaderName;		
			return SCARD_S_SUCCESS;
			}
		else{
			*pcchReaders = sizeof(szReaderName);
			}
		}

	if(mszReaders) memcpy(mszReaders, szReaderName, sizeof(szReaderName));

	return SCARD_S_SUCCESS;
}

LONG SProxyTransmit(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci, LPCBYTE pbSendBuffer, DWORD cbSendLength, LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength)
{
	B_CAS_PROXY *pCasProxy = (B_CAS_PROXY *)(hCard);
	if(!pCasProxy)return SCARD_E_READER_UNAVAILABLE;

	DWORD dwRecvLen = pCasProxy->transmit(pbSendBuffer, cbSendLength, pbRecvBuffer);
	if(pcbRecvLength)*pcbRecvLength = dwRecvLen;

	return (dwRecvLen)? SCARD_S_SUCCESS : SCARD_E_TIMEOUT;
}

LONG SProxyReleaseContext(SCARDCONTEXT hContext)
{
	return SCARD_S_SUCCESS;
}


// CCasProxy クラスのインプリメンテーション
//
//////////////////////////////////////////////////////////////////////

BOOL Connect(void)
{
	struct sockaddr_in client_addr;

	if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) <= 0) {
		return -1;
	}

  	bzero((char *)&client_addr, sizeof(client_addr));
	client_addr.sin_family = PF_INET;
	client_addr.sin_addr.s_addr = inet_addr(B25_SERVER_IP);
	client_addr.sin_port = htons(6900);

	if (connect(sockfd, (struct sockaddr *)&client_addr, sizeof(client_addr)) > 0) {
		close(sockfd);
		return FALSE;
	}
	return TRUE;

}

DWORD TransmitCommand(const BYTE *pSendData, const DWORD dwSendSize, BYTE *pRecvData)
{
	BYTE SendBuf[256];
	SendBuf[0] = (BYTE)dwSendSize;
	memcpy(&SendBuf[1], pSendData, dwSendSize);

    if (write(sockfd, SendBuf, dwSendSize + 1UL)) {};

    if (read(sockfd, &SendBuf[0], 1)) {};
    if (read(sockfd, pRecvData, SendBuf[0])) {};
		
	return SendBuf[0];
}

