OSDN Git Service

add b25-remote
authorlonginus <longinus@4e526526-5e11-4fc0-8910-f8fd03428081>
Sun, 6 Dec 2009 16:22:57 +0000 (16:22 +0000)
committerlonginus <longinus@4e526526-5e11-4fc0-8910-f8fd03428081>
Sun, 6 Dec 2009 16:22:57 +0000 (16:22 +0000)
git-svn-id: svn+ssh://svn.sourceforge.jp/svnroot/rec10@303 4e526526-5e11-4fc0-8910-f8fd03428081

17 files changed:
b25-remote/BCasCard.cpp [new file with mode: 0755]
b25-remote/BCasCard.h [new file with mode: 0755]
b25-remote/CasClient.cpp [new file with mode: 0755]
b25-remote/CasClient.h [new file with mode: 0755]
b25-remote/CasProxy.cpp [new file with mode: 0755]
b25-remote/CasProxy.h [new file with mode: 0755]
b25-remote/CasServer.cpp [new file with mode: 0755]
b25-remote/CasServer.h [new file with mode: 0755]
b25-remote/Makefile [new file with mode: 0755]
b25-remote/Readme.txt [new file with mode: 0755]
b25-remote/SmartSock.cpp [new file with mode: 0755]
b25-remote/SmartSock.h [new file with mode: 0755]
b25-remote/TsUtilClass.cpp [new file with mode: 0755]
b25-remote/TsUtilClass.h [new file with mode: 0755]
b25-remote/W2L.h [new file with mode: 0755]
b25-remote/b25-client.cpp [new file with mode: 0755]
b25-remote/b25-server.cpp [new file with mode: 0755]

diff --git a/b25-remote/BCasCard.cpp b/b25-remote/BCasCard.cpp
new file mode 100755 (executable)
index 0000000..7d8387f
--- /dev/null
@@ -0,0 +1,361 @@
+// BcasCard.cpp: CBcasCard \83N\83\89\83X\82Ì\83C\83\93\83v\83\8a\83\81\83\93\83e\81[\83V\83\87\83\93\r
+//\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+#include "W2L.h"\r
+#include "BCasCard.h"\r
+\r
+#ifdef _DEBUG\r
+#undef THIS_FILE\r
+static char THIS_FILE[]=__FILE__;\r
+#define new DEBUG_NEW\r
+#endif\r
+\r
+\r
+//#pragma comment(lib, "WinScard.lib")\r
+\r
+\r
+using std::auto_ptr;\r
+\r
+\r
+CBcasCard::CBcasCard()\r
+       : m_hBcasCard(NULL)\r
+       , m_bIsEstablish(false)\r
+       , m_dwLastError(BCEC_NOERROR)\r
+{\r
+       // \93à\95\94\8fó\91Ô\8f\89\8aú\89»\r
+       memset(&m_BcasCardInfo, 0, sizeof(m_BcasCardInfo));\r
+       memset(&m_EcmStatus,    0, sizeof(m_EcmStatus));\r
+\r
+       // \83\8a\83\\81[\83X\83}\83l\81[\83W\83\83\83R\83\93\83e\83L\83X\83g\8am\97§\r
+       if(::SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &m_ScardContext) != SCARD_S_SUCCESS){\r
+               m_dwLastError = BCEC_NOTESTABLISHED;\r
+               }\r
+       else{\r
+               m_bIsEstablish = true;\r
+               \r
+               // \83J\81[\83h\83\8a\81[\83_\97ñ\8b\93\r
+               EnumCardReader();\r
+               }\r
+}\r
+\r
+CBcasCard::~CBcasCard()\r
+{\r
+       CloseCard();\r
+\r
+       // \83\8a\83\\81[\83X\83}\83l\81[\83W\83\83\83R\83\93\83e\83L\83X\83g\82Ì\8aJ\95ú\r
+       if(m_bIsEstablish)::SCardReleaseContext(m_ScardContext);\r
+}\r
+\r
+const DWORD CBcasCard::GetCardReaderNum(void) const\r
+{\r
+       // \83J\81[\83h\83\8a\81[\83_\81[\90\94\82ð\95Ô\82·\r
+       return m_CardReaderArray.size();\r
+}\r
+\r
+LPCTSTR CBcasCard::GetCardReaderName(const DWORD dwIndex) const\r
+{\r
+       // \83J\81[\83h\83\8a\81[\83_\81[\96¼\82ð\95Ô\82·\r
+       return (dwIndex < GetCardReaderNum())? m_CardReaderArray[dwIndex].c_str() : NULL;\r
+}\r
+\r
+const bool CBcasCard::OpenCard(LPCTSTR lpszReader)\r
+{\r
+       // \83\8a\83\\81[\83X\83}\83l\81[\83W\83\83\83R\83\93\83e\83L\83X\83g\82Ì\8am\97§\r
+       if(!m_bIsEstablish){\r
+               m_dwLastError = BCEC_NOTESTABLISHED;\r
+               return false;\r
+               }\r
+       \r
+       // \88ê\92U\83N\83\8d\81[\83Y\82·\82é\r
+       CloseCard();\r
+\r
+\r
+       if(lpszReader){\r
+               // \8ew\92è\82³\82ê\82½\83J\81[\83h\83\8a\81[\83_\82É\91Î\82µ\82Ä\83I\81[\83v\83\93\82ð\8e\8e\82Ý\82é\r
+               DWORD dwActiveProtocol = SCARD_PROTOCOL_UNDEFINED;\r
+               \r
+               if(::SCardConnect(m_ScardContext, lpszReader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1, &m_hBcasCard, &dwActiveProtocol) != SCARD_S_SUCCESS){\r
+                       m_dwLastError = BCEC_CARDOPENERROR;\r
+                       return false;\r
+                       }\r
+\r
+               if(dwActiveProtocol != SCARD_PROTOCOL_T1){\r
+                       CloseCard();\r
+                       m_dwLastError = BCEC_CARDOPENERROR;\r
+                       return false;\r
+                       }\r
+               }\r
+       else{\r
+               // \91S\82Ä\82Ì\83J\81[\83h\83\8a\81[\83_\82É\91Î\82µ\82Ä\83I\81[\83v\83\93\82ð\8e\8e\82Ý\82é\r
+               DWORD dwIndex = 0UL;\r
+       \r
+               while(GetCardReaderName(dwIndex)){\r
+                       if(OpenCard(GetCardReaderName(dwIndex++)))return true;                  \r
+                       }\r
+               \r
+               return false;\r
+               }\r
+\r
+       // \83J\81[\83h\8f\89\8aú\89»\r
+       if(!InitialSetting())return false;\r
+\r
+       m_dwLastError = BCEC_NOERROR;\r
+\r
+       return true;\r
+}\r
+\r
+void CBcasCard::CloseCard(void)\r
+{\r
+       // \83J\81[\83h\82ð\83N\83\8d\81[\83Y\82·\82é\r
+       if(m_hBcasCard){\r
+               ::SCardDisconnect(m_hBcasCard, SCARD_LEAVE_CARD);\r
+               m_hBcasCard = NULL;\r
+               }\r
+}\r
+\r
+const DWORD CBcasCard::GetLastError(void) const\r
+{\r
+       // \8dÅ\8cã\82É\94­\90\82µ\82½\83G\83\89\81[\82ð\95Ô\82·\r
+       return m_dwLastError;\r
+}\r
+\r
+const bool CBcasCard::EnumCardReader(void)\r
+{\r
+       // \83J\81[\83h\83\8a\81[\83_\82ð\97ñ\8b\93\82·\82é\r
+       DWORD dwBuffSize = 0UL;\r
+       \r
+       switch(::SCardListReaders(m_ScardContext, NULL, NULL, &dwBuffSize)){\r
+               case SCARD_E_NO_READERS_AVAILABLE :\r
+                       // \83J\81[\83h\83\8a\81[\83_\82ª\8c©\82Â\82©\82ç\82È\82¢\r
+                       m_dwLastError = BCEC_NOCARDREADERS;\r
+                       return false;\r
+\r
+               case SCARD_S_SUCCESS :\r
+                       // \83o\83b\83t\83@\83T\83C\83Y\8eæ\93¾\90¬\8c÷\r
+                       break;\r
+               \r
+               default:\r
+                       // \83G\83\89\81[\r
+                       m_dwLastError = BCEC_INTERNALERROR;             \r
+                       return false;\r
+               }\r
+\r
+       // \83o\83b\83t\83@\8am\95Û\r
+       auto_ptr<TCHAR> szReaders(new TCHAR[dwBuffSize]);\r
+\r
+       switch(::SCardListReaders(m_ScardContext, NULL, szReaders.get(), &dwBuffSize)){\r
+               case SCARD_E_NO_READERS_AVAILABLE :\r
+                       // \83J\81[\83h\83\8a\81[\83_\82ª\8c©\82Â\82©\82ç\82È\82¢\r
+                       m_dwLastError = BCEC_NOCARDREADERS;\r
+                       return false;\r
+\r
+               case SCARD_S_SUCCESS : {\r
+                       // \83J\81[\83h\83\8a\81[\83_\96¼\95Û\91\r
+                       LPTSTR lpszCurReader = szReaders.get();\r
+                       m_CardReaderArray.clear();\r
+                       \r
+                       while(*lpszCurReader){\r
+                               m_CardReaderArray.push_back(lpszCurReader);\r
+                               lpszCurReader += m_CardReaderArray.back().length() + 1UL;\r
+                               }\r
+                       \r
+                       break;\r
+                       }\r
+               \r
+               default:\r
+                       // \83G\83\89\81[\r
+                       m_dwLastError = BCEC_INTERNALERROR;             \r
+                       return false;\r
+               }\r
+\r
+       m_dwLastError = BCEC_NOERROR;\r
+\r
+       return true;\r
+}\r
+\r
+const bool CBcasCard::TransmitCommand(const BYTE *pSendData, const DWORD dwSendSize, BYTE *pRecvData, const DWORD dwMaxRecv, DWORD *pdwRecvSize)\r
+{\r
+       DWORD dwRecvSize = dwMaxRecv;\r
+\r
+       // \83f\81[\83^\91\97\8eó\90M\r
+       DWORD dwReturn = ::SCardTransmit(m_hBcasCard, SCARD_PCI_T1, pSendData, dwSendSize, NULL, pRecvData, &dwRecvSize);\r
+       \r
+       // \8eó\90M\83T\83C\83Y\8ai\94[\r
+       if(pdwRecvSize)*pdwRecvSize = dwRecvSize;\r
+\r
+       return (dwReturn == SCARD_S_SUCCESS)? true : false;\r
+}\r
+\r
+const bool CBcasCard::InitialSetting(void)\r
+{\r
+       static const BYTE InitSettingCmd[] = {0x90U, 0x30U, 0x00U, 0x00U, 0x00U};\r
+\r
+       // \81uInitial Setting Conditions Command\81v\82ð\8f\88\97\9d\82·\82é\r
+       if(!m_hBcasCard){\r
+               m_dwLastError = BCEC_CARDNOTOPEN;\r
+               return false;\r
+               }\r
+\r
+       // \83o\83b\83t\83@\8f\80\94õ\r
+       DWORD dwRecvSize = 0UL;\r
+       BYTE RecvData[1024];\r
+       memset(RecvData, 0, sizeof(RecvData));\r
+       \r
+       // \83R\83}\83\93\83h\91\97\90M\r
+       if(!TransmitCommand(InitSettingCmd, sizeof(InitSettingCmd), RecvData, sizeof(RecvData), &dwRecvSize)){\r
+               m_dwLastError = BCEC_TRANSMITERROR;\r
+               return false;\r
+               }\r
+\r
+       if(dwRecvSize < 57UL){\r
+               m_dwLastError = BCEC_TRANSMITERROR;\r
+               return false;           \r
+               }\r
+\r
+       // \83\8c\83X\83|\83\93\83X\89ð\90Í\r
+       memcpy(m_BcasCardInfo.BcasCardID, &RecvData[8], 6UL);           // +8   Card ID\r
+       memcpy(m_BcasCardInfo.SystemKey, &RecvData[16], 32UL);  // +16  Descrambling system key\r
+       memcpy(m_BcasCardInfo.InitialCbc, &RecvData[48], 8UL);  // +48  Descrambler CBC initial value\r
+\r
+       // ECM\83X\83e\81[\83^\83X\8f\89\8aú\89»\r
+       memset(&m_EcmStatus, 0, sizeof(m_EcmStatus));\r
+\r
+       return true;\r
+}\r
+\r
+const BYTE * CBcasCard::GetBcasCardID(void)\r
+{\r
+       // Card ID \82ð\95Ô\82·\r
+       if(!m_hBcasCard){\r
+               m_dwLastError = BCEC_CARDNOTOPEN;\r
+               return NULL;\r
+               }\r
+       \r
+       m_dwLastError = BCEC_NOERROR;\r
+       \r
+       return m_BcasCardInfo.BcasCardID;\r
+}\r
+\r
+const BYTE * CBcasCard::GetInitialCbc(void)\r
+{\r
+       // Descrambler CBC Initial Value \82ð\95Ô\82·\r
+       if(!m_hBcasCard){\r
+               m_dwLastError = BCEC_CARDNOTOPEN;\r
+               return NULL;\r
+               }\r
+       \r
+       m_dwLastError = BCEC_NOERROR;\r
+       \r
+       return m_BcasCardInfo.InitialCbc;\r
+}\r
+\r
+const BYTE * CBcasCard::GetSystemKey(void)\r
+{\r
+       // Descrambling System Key \82ð\95Ô\82·\r
+       if(!m_hBcasCard){\r
+               m_dwLastError = BCEC_CARDNOTOPEN;\r
+               return NULL;\r
+               }\r
+       \r
+       m_dwLastError = BCEC_NOERROR;\r
+       \r
+       return m_BcasCardInfo.SystemKey;\r
+}\r
+\r
+const BYTE * CBcasCard::GetKsFromEcm(const BYTE *pEcmData, const DWORD dwEcmSize)\r
+{\r
+       static const BYTE EcmReceiveCmd[] = {0x90U, 0x34U, 0x00U, 0x00U};\r
+\r
+       // \81uECM Receive Command\81v\82ð\8f\88\97\9d\82·\82é\r
+       if(!m_hBcasCard){\r
+               m_dwLastError = BCEC_CARDNOTOPEN;\r
+               return NULL;\r
+               }\r
+\r
+       // ECM\83T\83C\83Y\82ð\83`\83F\83b\83N\r
+       if(!pEcmData || (dwEcmSize < 30UL) || (dwEcmSize > 256UL)){\r
+               m_dwLastError = BCEC_BADARGUMENT;\r
+               return NULL;\r
+               }\r
+\r
+       // \83L\83\83\83b\83V\83\85\82ð\83`\83F\83b\83N\82·\82é\r
+       if(!StoreEcmData(pEcmData, dwEcmSize)){\r
+               // ECM\82ª\93¯\88ê\82Ì\8fê\8d\87\82Í\83L\83\83\83b\83V\83\85\8dÏ\82ÝKs\82ð\95Ô\82·\r
+               m_dwLastError = BCEC_NOERROR;\r
+               return m_EcmStatus.KsData;\r
+               }\r
+\r
+       // \83o\83b\83t\83@\8f\80\94õ\r
+       DWORD dwRecvSize = 0UL;\r
+       BYTE SendData[1024];\r
+       BYTE RecvData[1024];\r
+       memset(RecvData, 0, sizeof(RecvData));\r
+\r
+       // \83R\83}\83\93\83h\8d\\92z\r
+       memcpy(SendData, EcmReceiveCmd, sizeof(EcmReceiveCmd));                         // CLA, INS, P1, P2\r
+       SendData[sizeof(EcmReceiveCmd)] = (BYTE)dwEcmSize;                                                      // COMMAND DATA LENGTH\r
+       memcpy(&SendData[sizeof(EcmReceiveCmd) + 1], pEcmData, dwEcmSize);      // ECM\r
+       SendData[sizeof(EcmReceiveCmd) + dwEcmSize + 1] = 0x00U;                                        // RESPONSE DATA LENGTH\r
+\r
+       // \83R\83}\83\93\83h\91\97\90M\r
+       if(!TransmitCommand(SendData, sizeof(EcmReceiveCmd) + dwEcmSize + 2UL, RecvData, sizeof(RecvData), &dwRecvSize)){\r
+               memset(&m_EcmStatus, 0, sizeof(m_EcmStatus));\r
+               m_dwLastError = BCEC_TRANSMITERROR;\r
+               return NULL;\r
+               }\r
+\r
+       // \83T\83C\83Y\83`\83F\83b\83N\r
+       if(dwRecvSize != 25UL){\r
+               memset(&m_EcmStatus, 0, sizeof(m_EcmStatus));\r
+               m_dwLastError = BCEC_TRANSMITERROR;\r
+               return NULL;\r
+               }       \r
+       \r
+       // \83\8c\83X\83|\83\93\83X\89ð\90Í\r
+       memcpy(m_EcmStatus.KsData, &RecvData[6], sizeof(m_EcmStatus.KsData));\r
+\r
+       // \83\8a\83^\81[\83\93\83R\81[\83h\89ð\90Í\r
+       switch(((WORD)RecvData[4] << 8) | (WORD)RecvData[5]){\r
+               // Purchased: Viewing\r
+               case 0x0200U :  // Payment-deferred PPV\r
+               case 0x0400U :  // Prepaid PPV\r
+               case 0x0800U :  // Tier\r
+                       m_dwLastError = BCEC_NOERROR;\r
+                       return m_EcmStatus.KsData;\r
+               \r
+               // \8fã\8bL\88È\8aO(\8e\8b\92®\95s\89Â)\r
+               default :\r
+                       m_dwLastError = BCEC_ECMREFUSED;\r
+                       return NULL;\r
+               }\r
+}\r
+\r
+const bool CBcasCard::StoreEcmData(const BYTE *pEcmData, const DWORD dwEcmSize)\r
+{\r
+       bool bUpdate = false;\r
+       \r
+       // ECM\83f\81[\83^\94ä\8ar\r
+       if(m_EcmStatus.dwLastEcmSize != dwEcmSize){\r
+               // \83T\83C\83Y\82ª\95Ï\89»\82µ\82½\r
+               bUpdate = true;\r
+               }\r
+       else{\r
+               // \83T\83C\83Y\82ª\93¯\82\8fê\8d\87\82Í\83f\81[\83^\82ð\83`\83F\83b\83N\82·\82é\r
+               for(DWORD dwPos = 0UL ; dwPos < dwEcmSize ; dwPos++){\r
+                       if(pEcmData[dwPos] != m_EcmStatus.LastEcmData[dwPos]){\r
+                               // \83f\81[\83^\82ª\95s\88ê\92v\r
+                               bUpdate = true;\r
+                               break;\r
+                               }                       \r
+                       }\r
+               }\r
+\r
+       // ECM\83f\81[\83^\82ð\95Û\91\82·\82é\r
+       if(bUpdate){\r
+               m_EcmStatus.dwLastEcmSize = dwEcmSize;\r
+               memcpy(m_EcmStatus.LastEcmData, pEcmData, dwEcmSize);\r
+               }\r
+\r
+       return bUpdate;\r
+}\r
diff --git a/b25-remote/BCasCard.h b/b25-remote/BCasCard.h
new file mode 100755 (executable)
index 0000000..e793203
--- /dev/null
@@ -0,0 +1,85 @@
+// BcasCard.h: CBcasCard \83N\83\89\83X\82Ì\83C\83\93\83^\81[\83t\83F\83C\83X\r
+//\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+#pragma once\r
+\r
+
+#include <memory>\r
+#include <vector>\r
+#include <string>\r
+#include <winscard.h>\r
+\r
+\r
+using std::vector;\r
+using std::wstring;\r
+using std::string;\r
+\r
+\r
+// \83G\83\89\81[\83R\81[\83h\r
+#define BCEC_NOERROR                   0x00000000UL    // \83G\83\89\81[\82È\82µ\r
+#define BCEC_INTERNALERROR             0x00000001UL    // \93à\95\94\83G\83\89\81[\r
+#define BCEC_NOTESTABLISHED            0x00000002UL    // \83R\83\93\83e\83L\83X\83g\8am\97§\8e¸\94s\r
+#define BCEC_NOCARDREADERS             0x00000003UL    // \83J\81[\83h\83\8a\81[\83_\82ª\82È\82¢\r
+#define BCEC_ALREADYOPEN               0x00000004UL    // \8aù\82É\83I\81[\83v\83\93\8dÏ\82Ý\r
+#define BCEC_CARDOPENERROR             0x00000005UL    // \83J\81[\83h\83I\81[\83v\83\93\8e¸\94s\r
+#define BCEC_CARDNOTOPEN               0x00000006UL    // \83J\81[\83h\96¢\83I\81[\83v\83\93\r
+#define BCEC_TRANSMITERROR             0x00000007UL    // \92Ê\90M\83G\83\89\81[\r
+#define BCEC_BADARGUMENT               0x00000008UL    // \88ø\90\94\82ª\95s\90³\r
+#define BCEC_ECMREFUSED                        0x00000009UL    // ECM\8eó\95t\8b\91\94Û\r
+\r
+\r
+class CBcasCard\r
+{\r
+public:\r
+       CBcasCard();\r
+       ~CBcasCard();\r
+\r
+       const DWORD GetCardReaderNum(void) const;\r
+       LPCTSTR GetCardReaderName(const DWORD dwIndex = 0UL) const;\r
+\r
+       const bool OpenCard(LPCTSTR lpszReader = NULL);\r
+       void CloseCard(void);\r
+\r
+       const BYTE * GetBcasCardID(void);\r
+       const BYTE * GetInitialCbc(void);\r
+       const BYTE * GetSystemKey(void);\r
+       const BYTE * GetKsFromEcm(const BYTE *pEcmData, const DWORD dwEcmSize);\r
+\r
+       const DWORD GetLastError(void) const;\r
+\r
+protected:\r
+       const bool EnumCardReader(void);\r
+       const bool TransmitCommand(const BYTE *pSendData, const DWORD dwSendSize, BYTE *pRecvData, const DWORD dwMaxRecv, DWORD *pdwRecvSize = NULL);\r
+       const bool InitialSetting(void);\r
+\r
+       SCARDCONTEXT m_ScardContext;\r
+       SCARDHANDLE m_hBcasCard;\r
+\r
+       bool m_bIsEstablish;\r
+\r
+#ifdef _UNICODE        \r
+       vector<wstring> m_CardReaderArray;\r
+#else\r
+       vector<string> m_CardReaderArray;\r
+#endif\r
+\r
+       struct TAG_BCASCARDINFO\r
+       {\r
+               BYTE BcasCardID[6];             // Card ID\r
+               BYTE SystemKey[32];             // Descrambling system key\r
+               BYTE InitialCbc[8];             // Descrambler CBC initial value\r
+       } m_BcasCardInfo;\r
+       \r
+       struct TAG_ECMSTATUS\r
+       {\r
+               DWORD dwLastEcmSize;    // \8dÅ\8cã\82É\96â\82¢\8d\87\82í\82¹\82Ì\82 \82Á\82½ECM\83T\83C\83Y\r
+               BYTE LastEcmData[256];  // \8dÅ\8cã\82É\96â\82¢\8d\87\82í\82¹\82Ì\82 \82Á\82½ECM\83f\81[\83^\r
+               BYTE KsData[16];                // Ks Odd + Even        \r
+       } m_EcmStatus;\r
+       \r
+       DWORD m_dwLastError;\r
+\r
+private:\r
+       const bool StoreEcmData(const BYTE *pEcmData, const DWORD dwEcmSize);\r
+};\r
diff --git a/b25-remote/CasClient.cpp b/b25-remote/CasClient.cpp
new file mode 100755 (executable)
index 0000000..4b6c6fb
--- /dev/null
@@ -0,0 +1,97 @@
+// CasClient.cpp: CCasClient \83N\83\89\83X\82Ì\83C\83\93\83v\83\8a\83\81\83\93\83e\81[\83V\83\87\83\93\r
+//\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+#include <stdio.h>\r
+#include "W2L.h"\r
+#include "CasClient.h"
+\r
+\r
+#define TCP_TIMEOUT            1000UL          // 1\95b\r
+\r
+\r
+CCasClient::CCasClient(ICasClientHandler *pEventHandler, CSmartSock *pSocket)\r
+       : CBcasCard()\r
+       , m_pSocket(pSocket)\r
+       , m_pEventHandler(pEventHandler)\r
+       , m_hClientThread(NULL)\r
+{\r
+       // \83N\83\89\83C\83A\83\93\83g\83X\83\8c\83b\83h\8bN\93®\r
+       pthread_create(&m_hClientThread, NULL, CCasClient::ClientThreadRaw, (LPVOID)this);\r
+       if(!m_hClientThread){\r
+               printf("ClientThread failed\n");
+               delete this;\r
+       }\r
+       printf("ClientThread started\n");
+}\r
+\r
+CCasClient::~CCasClient(void)\r
+{\r
+       delete m_pSocket;\r
+       if (m_hClientThread) pthread_join(m_hClientThread, NULL);\r
+}\r
+\r
+void CCasClient::CloseClient(void)\r
+{\r
+       // \83N\83\89\83C\83A\83\93\83g\82ð\90Ø\92f\82·\82é\r
+       m_pSocket->Close();\r
+}\r
+\r
+void CCasClient::ClientThread(void)\r
+{\r
+       // \83J\81[\83h\83\8a\81[\83_\82ð\8aJ\82­\r
+       if(!OpenCard())return;\r
+       \r
+       // \8eó\90M\83o\83b\83t\83@\r
+       BYTE byDataLen;\r
+       BYTE RecvBuf[256];\r
+       DWORD dwRecvSize;\r
+       \r
+       // \83\81\83b\83Z\81[\83W\8eó\90M\83\8b\81[\83v\r
+       while(1){\r
+               // \83w\83b\83_\82ð\8eó\90M\r
+               if(!m_pSocket->Recv(&byDataLen, 1UL, TCP_TIMEOUT)){\r
+                       if(m_pSocket->GetLastError() == CSmartSock::EC_TIMEOUT)continue;\r
+                       else break;\r
+               }
+\r
+               // \83f\81[\83^\82ð\8eó\90M\r
+               if(!m_pSocket->Recv(RecvBuf, byDataLen, TCP_TIMEOUT))break;
+       \r
+               // \83J\81[\83h\91\97\8eó\90M\r
+               if(!TransmitCommand(RecvBuf, byDataLen, &RecvBuf[1], sizeof(RecvBuf) - 1UL, &dwRecvSize))dwRecvSize = 0UL;
+\r
+               // \83f\81[\83^\82ð\91\97\90M\r
+               RecvBuf[0] = (BYTE)dwRecvSize;\r
+               if(!m_pSocket->Send(RecvBuf, dwRecvSize + 1UL, TCP_TIMEOUT))break;
+       }\r
+\r
+       printf("ClientThread exited\n");
+       // \83J\81[\83h\83\8a\81[\83_\82ð\95Â\82\82é\r
+       CloseCard();\r
+}\r
+\r
+void* CCasClient::ClientThreadRaw(LPVOID pParam)\r
+{\r
+       // \83N\83\89\83C\83A\83\93\83g\83X\83\8c\83b\83h\r
+       CCasClient *pThis = static_cast<CCasClient *>(pParam);\r
+\r
+       // \90Ú\91±\83C\83x\83\93\83g\92Ê\92m\r
+       pThis->SendEvent(EID_CONNECTED);
+\r
+       // \83\81\83\93\83o\8aÖ\90\94\82É\83\8a\83_\83C\83\8c\83N\83g\82·\82é\r
+       pThis->ClientThread();
+\r
+       // \90Ø\92f\83C\83x\83\93\83g\92Ê\92m\r
+       pThis->SendEvent(EID_DISCONNECTED);
+\r
+       delete pThis;
+\r
+       return 0UL;\r
+}\r
+\r
+void CCasClient::SendEvent(const DWORD dwEventID, PVOID pParam)\r
+{\r
+       // \83n\83\93\83h\83\89\82É\83C\83x\83\93\83g\82ð\92Ê\92m\82·\82é\r
+       if(m_pEventHandler)m_pEventHandler->OnCasClientEvent(this, dwEventID, pParam);\r
+}\r
diff --git a/b25-remote/CasClient.h b/b25-remote/CasClient.h
new file mode 100755 (executable)
index 0000000..ecd1c56
--- /dev/null
@@ -0,0 +1,41 @@
+// CasClient.h: CCasClient \83N\83\89\83X\82Ì\83C\83\93\83^\81[\83t\83F\83C\83X\r
+//\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+#pragma once\r
+\r
+#include "W2L.h"\r
+#include "BCasCard.h"\r
+#include "SmartSock.h"\r
+\r
+\r
+class CCasClient : private CBcasCard\r
+{\r
+public:\r
+       class ICasClientHandler\r
+       {\r
+       public:\r
+               virtual void OnCasClientEvent(CCasClient *pClient, const DWORD dwEventID, PVOID pParam) = 0;\r
+       };\r
+\r
+       enum\r
+       {\r
+               EID_CONNECTED,          // \83N\83\89\83C\83A\83\93\83g\90Ú\91±\r
+               EID_DISCONNECTED        // \83N\83\89\83C\83A\83\93\83g\90Ø\92f\r
+       };\r
+\r
+       CCasClient(ICasClientHandler *pEventHandler, CSmartSock *pSocket);\r
+       ~CCasClient(void);\r
+\r
+       void CloseClient(void);\r
+\r
+protected:\r
+       void ClientThread(void);\r
+       static void* ClientThreadRaw(LPVOID pParam);\r
+\r
+       void SendEvent(const DWORD dwEventID, PVOID pParam = NULL);\r
+\r
+       CSmartSock *m_pSocket;\r
+       ICasClientHandler *m_pEventHandler;\r
+       pthread_t m_hClientThread;\r
+};\r
diff --git a/b25-remote/CasProxy.cpp b/b25-remote/CasProxy.cpp
new file mode 100755 (executable)
index 0000000..dbf0330
--- /dev/null
@@ -0,0 +1,87 @@
+// CasProxy.cpp: CCasProxy \83N\83\89\83X\82Ì\83C\83\93\83v\83\8a\83\81\83\93\83e\81[\83V\83\87\83\93\r
+//\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+\r
+#include "CasProxy.h"\r
+#include <stdio.h>\r
+\r
+#define TCP_TIMEOUT    1000UL  // 1\95b\r
+\r
+\r
+DWORD CCasProxy::dwErrorDelayTime = 0UL;\r
+\r
+\r
+CCasProxy::CCasProxy(void)\r
+{\r
+\r
+}\r
+\r
+CCasProxy::~CCasProxy(void)\r
+{\r
+       // \83T\81[\83o\82©\82ç\90Ø\92f\r
+       m_Socket.Close();\r
+}\r
+\r
+const BOOL CCasProxy::Connect(void)\r
+{\r
+/*
+       // \83G\83\89\81[\94­\90\8e\9e\82Ì\83K\81[\83h\83C\83\93\83^\81[\83o\83\8b\r
+       if(dwErrorDelayTime){\r
+               if((::GetTickCount() - dwErrorDelayTime) < TCP_TIMEOUT)return FALSE;\r
+               else dwErrorDelayTime = 0UL;\r
+               }\r
+*/\r
+       // \83T\81[\83o\82É\90Ú\91±
+       char* env = getenv("B25_SERVER_IP");
+       LPCTSTR lpszHost;
+       WORD wPort;
+       if (env) {
+               lpszHost = env;
+       }
+       else {
+               lpszHost = "127.0.0.1";
+       }
+       env = getenv("B25_SERVER_PORT");
+       if (env) {
+               wPort = atoi(env);
+       }
+       else {
+               wPort = 6900;
+       }
+
+       if(m_Socket.Connect(lpszHost, wPort, TCP_TIMEOUT)){\r
+               return TRUE;\r
+       }\r
+       else{
+               //dwErrorDelayTime = ::GetTickCount();\r
+               return FALSE;\r
+       }\r
+}\r
+\r
+const DWORD CCasProxy::TransmitCommand(const BYTE *pSendData, const DWORD dwSendSize, BYTE *pRecvData)\r
+{\r
+       // \91\97\90M\83f\81[\83^\8f\80\94õ\r
+       BYTE SendBuf[256];\r
+       SendBuf[0] = (BYTE)dwSendSize;\r
+       memcpy(&SendBuf[1], pSendData, dwSendSize);\r
+\r
+       try{\r
+               // \83\8a\83N\83G\83X\83g\91\97\90M\r
+               if(!m_Socket.Send(SendBuf, dwSendSize + 1UL, TCP_TIMEOUT))throw (const DWORD)__LINE__;\r
+       \r
+               // \83\8c\83X\83|\83\93\83X\83w\83b\83_\8eó\90M\r
+               if(!m_Socket.Recv(SendBuf, 1UL, TCP_TIMEOUT))throw (const DWORD)__LINE__;\r
+\r
+               // \83\8c\83X\83|\83\93\83X\83f\81[\83^\8eó\90M\r
+               if(!m_Socket.Recv(pRecvData, SendBuf[0], TCP_TIMEOUT))throw (const DWORD)__LINE__;\r
+               }\r
+       catch(const DWORD dwLine){\r
+               // \92Ê\90M\83G\83\89\81[\94­\90\r
+               m_Socket.Close();\r
+               return 0UL;\r
+               }\r
+               \r
+       return SendBuf[0];\r
+}
+
diff --git a/b25-remote/CasProxy.h b/b25-remote/CasProxy.h
new file mode 100755 (executable)
index 0000000..2b0d6e4
--- /dev/null
@@ -0,0 +1,36 @@
+// CasProxy.h: CCasProxy \83N\83\89\83X\82Ì\83C\83\93\83^\81[\83t\83F\83C\83X\r
+//\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+\r
+#pragma once\r
+\r
+\r
+#include "SmartSock.h"\r
+#include <stdlib.h>\r
+\r
+class CCasProxy\r
+{\r
+public:\r
+       enum\r
+       {\r
+               CPEI_ENTERPROCESS,              // \83v\83\8d\83Z\83X\8aJ\8en\92Ê\92m\r
+               CPEI_EXITPROCESS,               // \83v\83\8d\83Z\83X\8fI\97¹\92Ê\92m\r
+               CPEI_GETSERVERIP,               // \83T\81[\83oIP\8eæ\93¾\r
+               CPEI_GETSERVERPORT,             // \83T\81[\83o\83|\81[\83g\8eæ\93¾\r
+               CPEI_CONNECTSUCCESS,    // \90Ú\91±\8a®\97¹\r
+               CPEI_CONNECTFAILED,             // \90Ú\91±\8e¸\94s\r
+               CPEI_DISCONNECTED               // \90Ú\91±\90Ø\92f\r
+       };\r
+       \r
+       CCasProxy(void);\r
+       ~CCasProxy(void);\r
+\r
+       const BOOL Connect(void);\r
+       const DWORD TransmitCommand(const BYTE *pSendData, const DWORD dwSendSize, BYTE *pRecvData);\r
+\r
+protected:\r
+       CSmartSock m_Socket;\r
+       \r
+       static DWORD dwErrorDelayTime;\r
+};\r
diff --git a/b25-remote/CasServer.cpp b/b25-remote/CasServer.cpp
new file mode 100755 (executable)
index 0000000..4c733b8
--- /dev/null
@@ -0,0 +1,110 @@
+// CasServer.cpp: CCasServer \83N\83\89\83X\82Ì\83C\83\93\83v\83\8a\83\81\83\93\83e\81[\83V\83\87\83\93\r
+//\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+\r
+#include "CasServer.h"\r
+#include "BCasCard.h"\r
+\r
+#define FALSE 0
+#define TRUE 1\r
+\r
+CCasServer::CCasServer(ICasServerHandler *pEventHandler)\r
+       : m_pEventHandler(pEventHandler)\r
+       , m_hServerThread(NULL)\r
+{\r
+\r
+}\r
+\r
+CCasServer::~CCasServer(void)\r
+{\r
+       CloseServer();\r
+}\r
+\r
+const BOOL CCasServer::OpenServer(const WORD wServerPort)\r
+{\r
+       // \83J\81[\83h\83\8a\81[\83_\91\8dÝ\83`\83F\83b\83N\r
+       CBcasCard BCasCard;\r
+       if(!BCasCard.OpenCard())return FALSE;\r
+\r
+       // \83T\81[\83o\83\\83P\83b\83g\83I\81[\83v\83\93\r
+       if(!m_pSocket.Listen(wServerPort))return FALSE;\r
+\r
+       // \83T\81[\83o\83X\83\8c\83b\83h\8bN\93®\r
+       pthread_create(&m_hServerThread, NULL, CCasServer::ServerThreadRaw, (LPVOID)this);\r
+       if(!m_hServerThread){\r
+               m_pSocket.Close();\r
+               return FALSE;\r
+       }\r
+\r
+       return TRUE;\r
+}\r
+\r
+void CCasServer::CloseServer(void)\r
+{\r
+       // \83T\81[\83o\83\\83P\83b\83g\83N\83\8d\81[\83Y\r
+       m_pSocket.Close();\r
+\r
+       // \83X\83\8c\83b\83h\83n\83\93\83h\83\8b\8aJ\95ú\r
+       if(m_hServerThread){\r
+               pthread_join(m_hServerThread, NULL);\r
+               m_hServerThread = NULL;\r
+       }\r
+\r
+       // \91S\83N\83\89\83C\83A\83\93\83g\90Ø\92f\r
+       m_Lock.Lock();\r
+       \r
+       for(ClientList::iterator It = m_ClientList.begin() ; It != m_ClientList.end() ; It++){\r
+               It->first->CloseClient();\r
+               }\r
+\r
+       m_Lock.Unlock();\r
+       \r
+       // \91S\83N\83\89\83C\83A\83\93\83g\82Ì\8fI\97¹\82ð\91Ò\82Â\r
+       while(m_ClientList.size()) sleep(1UL);\r
+}\r
+\r
+const DWORD CCasServer::GetClientNum(void) const\r
+{\r
+       // \90Ú\91±\92\86\82Ì\83N\83\89\83C\83A\83\93\83g\90\94\82ð\95Ô\82·\r
+       return m_ClientList.size();\r
+}\r
+\r
+void CCasServer::OnCasClientEvent(CCasClient *pClient, const DWORD dwEventID, PVOID pParam)\r
+{\r
+       CBlockLock AutoLock(&m_Lock);\r
+\r
+       // \83N\83\89\83C\83A\83\93\83g\83C\83x\83\93\83g\r
+       switch(dwEventID){\r
+               case CCasClient::EID_CONNECTED :\r
+                       // \83\8a\83X\83g\82É\92Ç\89Á\r
+                       m_ClientList[pClient] = pClient;\r
+                       if (m_pEventHandler) m_pEventHandler->OnCasServerEvent(this, CSEI_CONNECTED);\r
+                       break;\r
+                       \r
+               case CCasClient::EID_DISCONNECTED :\r
+                       // \83\8a\83X\83g\82©\82ç\8dí\8f\9c\r
+                       m_ClientList.erase(pClient);\r
+                       if (m_pEventHandler) m_pEventHandler->OnCasServerEvent(this, CSEI_DISCONNECTED);\r
+                       break;\r
+               }\r
+}\r
+\r
+void CCasServer::ServerThread(void)\r
+{\r
+       // \83A\83N\83Z\83v\83g\83\8b\81[\83v\r
+       CSmartSock *pNewSocket;\r
+       \r
+       while(pNewSocket = m_pSocket.Accept()){\r
+               // \83N\83\89\83C\83A\83\93\83g\83C\83\93\83X\83^\83\93\83X\90\90¬\r
+               new CCasClient(this, pNewSocket);\r
+               }\r
+}\r
+\r
+void* CCasServer::ServerThreadRaw(LPVOID pParam)\r
+{\r
+       // \83T\81[\83o\83X\83\8c\83b\83h\r
+       static_cast<CCasServer *>(pParam)->ServerThread();\r
+\r
+       return 0UL;\r
+}\r
diff --git a/b25-remote/CasServer.h b/b25-remote/CasServer.h
new file mode 100755 (executable)
index 0000000..35d7732
--- /dev/null
@@ -0,0 +1,56 @@
+// CasServer.h: CCasServer \83N\83\89\83X\82Ì\83C\83\93\83^\81[\83t\83F\83C\83X\r
+//\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+#pragma once\r
+\r
+\r
+#include <map>\r
+#include "CasClient.h"\r
+#include "TsUtilClass.h"\r
+#include "SmartSock.h"\r
+\r
+\r
+using std::map;\r
+\r
+\r
+class CCasServer : protected CCasClient::ICasClientHandler\r
+{\r
+public:\r
+       class ICasServerHandler\r
+       {\r
+       public:\r
+               virtual void OnCasServerEvent(CCasServer *pCasServer, const WORD wEventID) = 0;\r
+       };\r
+\r
+       enum\r
+       {\r
+               CSEI_CONNECTED,         // \83N\83\89\83C\83A\83\93\83g\90Ú\91±\r
+               CSEI_DISCONNECTED,      // \83N\83\89\83C\83A\83\93\83g\90Ø\92f\r
+       };\r
+\r
+       CCasServer(void);\r
+       CCasServer(ICasServerHandler *pEventHandler);\r
+       ~CCasServer(void);\r
+\r
+       const BOOL OpenServer(const WORD wServerPort);\r
+       void CloseServer(void);\r
+       \r
+       const DWORD GetClientNum(void) const;\r
+\r
+protected:\r
+       virtual void OnCasClientEvent(CCasClient *pClient, const DWORD dwEventID, PVOID pParam);\r
+\r
+       void ServerThread(void);\r
+       static void* ServerThreadRaw(LPVOID pParam);\r
+\r
+       ICasServerHandler *m_pEventHandler;\r
+\r
+       CSmartSock m_pSocket;\r
+       pthread_t m_hServerThread;
+\r
+       typedef map<CCasClient *, CCasClient *> ClientList;\r
+       ClientList m_ClientList;\r
+       \r
+       CCriticalLock m_Lock;\r
+};\r
diff --git a/b25-remote/Makefile b/b25-remote/Makefile
new file mode 100755 (executable)
index 0000000..ed4d823
--- /dev/null
@@ -0,0 +1,45 @@
+PREFIX                 = /usr/local
+TARGET_SERVER          = b25-server
+TARGET_CLIENT          = b25-client.so
+OBJ_SERVER             = BCasCard.o CasClient.o CasServer.o SmartSock.o TsUtilClass.o b25-server.o
+HEADER_SERVER          = BCasCard.h CasClient.h CasServer.h SmartSock.h TsUtilClass.h
+OBJ_CLIENT             = CasProxy.o SmartSock.o b25-client.o
+HEADER_CLIENT          = CasProxy.h SmartSock.h
+PCSC_CFLAGS            = `pkg-config libpcsclite --cflags`
+PCSC_LDLIBS            = `pkg-config libpcsclite --libs`
+
+CC                     = g++
+CFLAGS                 = -fPIC -O2 -Wall -g ${PCSC_CFLAGS}
+CFLAGS_FOR_LIB = -fPIC -shared
+LDFLAGS                = -pthread ${PCSC_LDLIBS}
+LIBS                   = 
+
+.cpp.o:
+                       ${CC} $(CFLAGS) -c $<
+
+.c.o:
+                       ${CC} $(CFLAGS) -c $<
+
+all:                   ${TARGET_SERVER} ${TARGET_CLIENT}
+
+${TARGET_SERVER}:      ${OBJ_SERVER}
+                       ${CC} ${CFLAGS} ${OBJ_SERVER} -o $@ ${LDFLAGS} ${LIBS}
+
+${TARGET_CLIENT}:      ${OBJ_CLIENT}
+                       ${CC} ${CFLAGS_FOR_LIB} ${OBJ_CLIENT} -o $@ ${LDFLAGS} ${LIBS}
+
+${OBJ_SERVER}: ${HEADER_SERVER}
+
+${OBJ_CLIENT}: ${HEADER_CLIENT}
+
+install:               ${TARGET_SERVER} ${TARGET_CLIENT}
+                       install -m755 ${TARGET_SERVER} ${PREFIX}/bin
+                       install -m755 ${TARGET_CLIENT} ${PREFIX}/lib
+
+uninstall:
+                       rm ${PREFIX}/bin/${TARGET_SERVER}
+                       rm ${PREFIX}/lib/${TARGET_CLIENT}
+
+clean:
+                       rm -f core ${TARGET_SERVER} *.o *.so
+
diff --git a/b25-remote/Readme.txt b/b25-remote/Readme.txt
new file mode 100755 (executable)
index 0000000..0f591d0
--- /dev/null
@@ -0,0 +1,56 @@
+
+- b25-remote Ver.0.0.1 -
+
+
+1.概要
+  ・スマートカードリーダをLANを経由で共有するためのシステムです。
+  ・BonCasLink互換プロトコルを使用します。
+
+ 
+2.注意事項
+  ・一般的にスマートカードには個人を特定可能な情報が含まれている可能性があります。
+  ・本ソフトウェアは通信の暗号化を行わないためこのリスクを十分に考えた上でご使用ください。
+  ・本ソフトウェアの警告を無視しLAN以外のネットワークにおいて使用した結果発生したいかなる
+   損害も作者に責任を求めないこととします。
+
+
+3.ライセンスについて
+  ・本パッケージに含まれる全てのソースコード、バイナリについて著作権は一切主張しません。
+  ・オリジナルのまま又は改変し、各自のソフトウェアに自由に添付、組み込むことができます。
+  ・但しGPLに従うことを要求しますのでこれらを行う場合はソースコードの開示が必須となります。
+  ・このとき本ソフトウェアの著作権表示を行うかどうかは任意です。
+
+  ・通信プロトコルの変更及び追加を含むソースコードの改変は一切許可できません。
+  ・上記を禁止するいかなる根拠または拘束力も作者にはありませんがこれに反して、
+   作成した改変物を配布する場合は下記を要求します。
+  ・ソフトウェアの名称を「b25-remote」以外に変更すること。
+  ・「Rec10」の著作権表示を一切行わないこと。
+  ・ソースコードの流用元の表示を一切行わないこと。
+  ・このソースコードは拡張ツール中の人(nakanohito@2sen.dip.jp)が作成されたBonCasLink(公式サイト:http://2sen.dip.jp/friio/)のソースコードを流用しています。
+
+  ・ビルドに必要な環境
+   - pcsc-lite-devel ※Fedora系
+   - libpcsclite-dev ※Debian系
+
+
+4.使用方法
+  ①スマートカードリーダが接続されたPCで「b25-server」を起動します。
+
+  ②LANに参加している他のPCでPCSCを利用するアプリケーションを起動します。
+
+  ③このとき環境変数を以下のように設定します。
+   LD_PRELOAD      = {b25-client.soの絶対パス}
+   B25_REMOTE_IP   = {サーバーのアドレス(DNS可)}
+   B25_REMOTE_PORT = {サーバーの使用ポート(デフォルト:6900)}
+
+   ※ファイヤウォールやフィルタリングを使用している場合は共有に使用するポートを開放してください。
+
+
+6.サポート、連絡先
+   連絡先  : Rec10
+   公式サイト: http://sourceforge.jp/projects/rec10/
+
+
+8.更新履歴
+ Ver.0.0.1 ・初回リリース
+
diff --git a/b25-remote/SmartSock.cpp b/b25-remote/SmartSock.cpp
new file mode 100755 (executable)
index 0000000..cbf802c
--- /dev/null
@@ -0,0 +1,572 @@
+// SmartSock.cpp: CSmartSock \83N\83\89\83X\82Ì\83C\83\93\83v\83\8a\83\81\83\93\83e\81[\83V\83\87\83\93\r
+//\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+#include "SmartSock.h"\r
+#include <stdio.h>
+#include <sys/time.h>\r
+\r
+#ifdef _DEBUG\r
+#define new DEBUG_NEW\r
+#endif\r
+
+//#pragma warning(disable: 4101) // warning C4101: "\83\8d\81[\83J\83\8b\95Ï\90\94\82Í 1 \93x\82à\8eg\82í\82ê\82Ä\82¢\82Ü\82¹\82ñ\81B"\r
+//#pragma warning(disable: 4996) // warning C4996: "This function or variable may be unsafe. Consider using _wsplitpath_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details"\r
+\r
+\r
+//#pragma comment(lib, "WS2_32")\r
+\r
+\r
+//////////////////////////////////////////////////////////////////////\r
+// \83}\83N\83\8d\92è\8b`\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+#define CHECK_FREESOCK(R)      if(m_Socket != INVALID_SOCKET){m_dwLastError = EC_SOCKINVALID; return (R);}\r
+#define CHECK_TCPSOCK(R)       if((m_Socket == INVALID_SOCKET) || (m_bSockType != SOCKTYPE_TCP)){m_dwLastError = EC_SOCKINVALID; return (R);}\r
+#define CHECK_UDPSOCK(R)       if((m_Socket == INVALID_SOCKET) || (m_bSockType != SOCKTYPE_UDP)){m_dwLastError = EC_SOCKINVALID; return (R);}\r
+\r
+\r
+//////////////////////////////////////////////////////////////////////\r
+// \8d\\92z/\8fÁ\96Å\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+DWORD CSmartSock::dwInstanceNum = 0UL;\r
+\r
+CSmartSock::CSmartSock()\r
+       : m_Socket(INVALID_SOCKET)\r
+       , m_bSockType(SOCKTYPE_NON)\r
+       , m_dwLastError(EC_NOERROR)\r
+{\r
+       // WinSock2\8f\89\8aú\89»\r
+       if(!(dwInstanceNum++))InitWinSock2();\r
+}\r
+\r
+CSmartSock::~CSmartSock()\r
+{\r
+       Close();\r
+\r
+       // WinSock2\8aJ\95ú\r
+       if(!(--dwInstanceNum))FreeWinSock2();\r
+}\r
+\r
+const BOOL CSmartSock::Connect(LPCTSTR lpszHost, const WORD wPort, const DWORD dwTimeOut)\r
+{\r
+       CHECK_FREESOCK(FALSE);\r
+\r
+       if(!lpszHost){\r
+               m_dwLastError = EC_PARAMINVALID;\r
+               return FALSE;\r
+               }\r
+               \r
+       // \83A\83h\83\8c\83X\96¼\82©\82çIP\83A\83h\83\8c\83X\8eæ\93¾\r
+       const DWORD dwIP = HostToIP(lpszHost);\r
+\r
+       if(dwIP == INADDR_NONE){\r
+               m_dwLastError = EC_SOCKERROR;\r
+               return FALSE;           \r
+               }\r
+       \r
+       return Connect(dwIP, wPort, dwTimeOut);\r
+}\r
+\r
+const BOOL CSmartSock::Connect(const DWORD dwIP, const WORD wPort, const DWORD dwTimeOut)\r
+{\r
+       CHECK_FREESOCK(FALSE);\r
+\r
+       // \83\\83P\83b\83g\8dì\90¬\r
+       if((m_Socket = ::socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET){\r
+               m_dwLastError = EC_SOCKERROR;\r
+               return FALSE;           \r
+               }\r
+\r
+       // \83A\83h\83\8c\83X\90Ý\92è\r
+       SOCKADDR_IN SockAddr;\r
+       SockAddr.sin_family = AF_INET;\r
+       SockAddr.sin_port = htons(wPort);\r
+       SockAddr.sin_addr.s_addr = htonl(dwIP);\r
+\r
+       // \93¯\8aú\83R\83l\83N\83g\r
+       if(!dwTimeOut){\r
+               if(::connect(m_Socket, (PSOCKADDR)&SockAddr, sizeof(sockaddr))){\r
+                       Close();\r
+                       m_dwLastError = EC_SOCKERROR;\r
+                       return FALSE;           \r
+                       }\r
+       \r
+               m_dwLastError = EC_NOERROR;\r
+               return TRUE;\r
+       }\r
+\r
+       // \94ñ\93¯\8aú\83R\83l\83N\83g\r
+       u_long nArg;\r
+       fd_set FdSet;\r
+       struct timeval TimeVal;\r
+       TimeVal.tv_sec = 10UL;\r
+       TimeVal.tv_usec = 0UL;
+       nArg = fcntl(m_Socket, F_GETFL, 0);\r
+       FD_ZERO(&FdSet);\r
+       FD_SET(m_Socket, &FdSet);\r
+\r
+       try{\r
+               // \94ñ\93¯\8aú\82É\90Ø\82è\91Ö\82¦\r
+               if(::fcntl(m_Socket, F_SETFL, nArg | O_NONBLOCK) == SOCKET_ERROR)throw (const DWORD)__LINE__;\r
+\r
+               // \83R\83l\83N\83g\r
+               if(::connect(m_Socket, (PSOCKADDR)&SockAddr, sizeof(sockaddr)) != SOCKET_ERROR)throw (const DWORD)__LINE__;\r
+\r
+               if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINPROGRESS)throw (const DWORD)__LINE__;\r
+\r
+               // \90Ú\91±\8a®\97¹\91Ò\82¿\r
+               if(!::select(32, NULL, &FdSet, NULL, &TimeVal))throw (const DWORD)__LINE__;\r
+\r
+               // \83^\83C\83\80\83A\83E\83g\94»\92è\r
+               if(!FD_ISSET(m_Socket, &FdSet)){\r
+                       Close();\r
+                       m_dwLastError = EC_TIMEOUT;\r
+                       return FALSE;\r
+                       }\r
+\r
+               // \93¯\8aú\82É\90Ø\82è\91Ö\82¦\r
+               if(::fcntl(m_Socket, F_SETFL, nArg) == SOCKET_ERROR)throw (const DWORD)__LINE__;\r
+               }\r
+       catch(const DWORD dwLine){\r
+               // \83G\83\89\81[\94­\90\r
+               Close();\r
+               m_dwLastError = EC_SOCKERROR;\r
+               return FALSE;\r
+               }\r
+\r
+       m_bSockType = SOCKTYPE_TCP;\r
+       m_dwLastError = EC_NOERROR;\r
+\r
+       return TRUE;\r
+}\r
+\r
+const BOOL CSmartSock::Listen(const WORD wPort)\r
+{\r
+       CHECK_FREESOCK(FALSE);\r
+\r
+       // \83\\83P\83b\83g\8dì\90¬\r
+       if((m_Socket = ::socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET){\r
+               m_dwLastError = EC_SOCKERROR;\r
+               return FALSE;           \r
+               }\r
+\r
+       // \83A\83h\83\8c\83X\90Ý\92è\r
+       SOCKADDR_IN SockAddr;\r
+       SockAddr.sin_family = AF_INET;\r
+       SockAddr.sin_port = htons(wPort);\r
+       SockAddr.sin_addr.s_addr = INADDR_ANY;\r
+\r
+       try{\r
+               // \81u\83A\83h\83\8c\83X\8eg\97p\92\86\81v\83G\83\89\81[\82ð\89ñ\94ð
+               int on = 1;
+               setsockopt(m_Socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+
+               // \83o\83C\83\93\83h\r
+               if(::bind(m_Socket, (PSOCKADDR)&SockAddr, sizeof(SockAddr)) == SOCKET_ERROR)throw (const DWORD)__LINE__;\r
+\r
+               // \90Ú\91±\8eó\82¯\93ü\82ê\r
+               if(::listen(m_Socket, 5) == SOCKET_ERROR)throw (const DWORD)__LINE__;\r
+               }\r
+       catch(const DWORD dwLine){\r
+               // \83G\83\89\81[\94­\90\r
+               Close();\r
+               m_dwLastError = EC_SOCKERROR;\r
+               return FALSE;\r
+               }\r
+\r
+       m_bSockType = SOCKTYPE_TCP;\r
+       m_dwLastError = EC_NOERROR;\r
+\r
+       return TRUE;\r
+}\r
+\r
+CSmartSock * CSmartSock::Accept(void)\r
+{\r
+       CHECK_TCPSOCK(FALSE);\r
+       \r
+       SOCKADDR_IN AddrIn;\r
+       memset(&AddrIn, 0, sizeof(AddrIn));\r
+       socklen_t iAddrLen = sizeof(AddrIn);\r
+\r
+       // \83R\83l\83N\83g\8eó\82¯\93ü\82ê\r
+       SOCKET SockIn = ::accept(m_Socket, (sockaddr *)&AddrIn, &iAddrLen);\r
+\r
+       if(SockIn == INVALID_SOCKET){\r
+               Close();\r
+               m_dwLastError = EC_SOCKERROR;\r
+               return NULL;\r
+               }\r
+\r
+       CSmartSock *pNewSock = new CSmartSock;\r
+       pNewSock->m_Socket = SockIn;\r
+       pNewSock->m_bSockType = SOCKTYPE_TCP;\r
+\r
+       m_dwLastError = EC_NOERROR;\r
+\r
+       return pNewSock;\r
+}\r
+\r
+const BOOL CSmartSock::Send(const BYTE *pBuff, const DWORD dwLen, const DWORD dwTimeOut)\r
+{\r
+       CHECK_TCPSOCK(FALSE);\r
+\r
+       if(!pBuff || !dwLen){\r
+               m_dwLastError = EC_PARAMINVALID;\r
+               return FALSE;\r
+               }\r
+\r
+       // \8ew\92è\83T\83C\83Y\91\97\90M\r
+       DWORD dwRef = 0UL, dwSend = 0UL;\r
+\r
+       do{
+               dwRef = SendOnce(pBuff + dwSend, dwLen - dwSend, dwTimeOut);
+               if(!dwRef) return FALSE;\r
+       }\r
+       while((dwSend += dwRef) < dwLen);\r
+\r
+       return TRUE;\r
+}\r
+\r
+const BOOL CSmartSock::Recv(BYTE *pBuff, const DWORD dwLen, const DWORD dwTimeOut)\r
+{\r
+       CHECK_TCPSOCK(FALSE);\r
+\r
+       if(!pBuff || !dwLen){\r
+               m_dwLastError = EC_PARAMINVALID;\r
+               return FALSE;\r
+       }\r
+\r
+       // \8ew\92è\83T\83C\83Y\8eó\90M\r
+       DWORD dwRef = 0UL, dwRecv = 0UL;\r
+
+       do{\r
+               if(!(dwRef = RecvOnce(pBuff + dwRecv, dwLen - dwRecv, dwTimeOut)))return FALSE;\r
+       }\r
+       while((dwRecv += dwRef) < dwLen);
+\r
+       return TRUE;\r
+}\r
+\r
+const DWORD CSmartSock::SendOnce(const BYTE *pBuff, const DWORD dwMaxLen, const DWORD dwTimeOut)\r
+{\r
+       CHECK_TCPSOCK(0UL);\r
+\r
+       if(!pBuff || !dwMaxLen){\r
+               m_dwLastError = EC_PARAMINVALID;\r
+               return FALSE;\r
+               }\r
+       \r
+       // \83^\83C\83\80\83A\83E\83g\90Ý\92è\r
+       struct timeval stTimeOut;\r
+\r
+       stTimeOut.tv_sec = 10UL;
+       stTimeOut.tv_usec = 0UL;\r
+       if(::setsockopt(m_Socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&stTimeOut, sizeof(struct timeval))){\r
+               Close();\r
+               m_dwLastError = EC_SOCKERROR;
+               return 0UL;\r
+       }\r
+
+       // \91\97\90M\r
+       const int iRef = ::send(m_Socket, (const char *)pBuff, dwMaxLen, 0);\r
+\r
+       if((iRef == SOCKET_ERROR) || !iRef){\r
+               if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS){\r
+                       m_dwLastError = EC_TIMEOUT;\r
+                       return 0UL;\r
+                       }\r
+               else{\r
+                       Close();\r
+                       m_dwLastError = EC_SOCKERROR;\r
+                       return 0UL;\r
+                       }\r
+               }\r
+               \r
+       m_dwLastError = EC_NOERROR;\r
+               \r
+       return (DWORD)iRef;\r
+}\r
+\r
+const DWORD CSmartSock::RecvOnce(BYTE *pBuff, const DWORD dwMaxLen, const DWORD dwTimeOut)\r
+{\r
+       CHECK_TCPSOCK(0UL);\r
+       \r
+       if(!pBuff || !dwMaxLen){\r
+               m_dwLastError = EC_PARAMINVALID;\r
+               return FALSE;\r
+               }\r
+\r
+       // \83^\83C\83\80\83A\83E\83g\92l\90Ý\92è\r
+       struct timeval stTimeOut;\r
+
+       stTimeOut.tv_sec = 10UL;
+       stTimeOut.tv_usec = 0UL;\r
+       if(::setsockopt(m_Socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&stTimeOut, sizeof(struct timeval))){\r
+               Close();\r
+               m_dwLastError = EC_SOCKERROR;
+               return 0UL;\r
+       }\r
+       
+       // \8eó\90M\r
+       int iRef = ::recv(m_Socket, (char *)pBuff, dwMaxLen, 0);\r
+\r
+       if((iRef == SOCKET_ERROR) || !iRef){
+               if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS){
+                       m_dwLastError = EC_TIMEOUT;\r
+                       return 0UL;\r
+                       }\r
+               else{\r
+                       Close();\r
+                       m_dwLastError = EC_SOCKERROR;\r
+                       return 0UL;\r
+                       }\r
+               }\r
+
+       m_dwLastError = EC_NOERROR;\r
+               \r
+       return (DWORD)iRef;\r
+}\r
+\r
+const BOOL CSmartSock::GetLocalAddr(DWORD *pdwIP, WORD *pwPort)\r
+{\r
+       CHECK_TCPSOCK(FALSE);\r
+\r
+       struct sockaddr_in LocalAddr;\r
+       socklen_t AddrLen = sizeof(LocalAddr);\r
+       \r
+       // \83\8d\81[\83J\83\8b\83A\83h\83\8c\83X\8eæ\93¾\r
+       if(::getsockname(m_Socket, (struct sockaddr *)&LocalAddr, &AddrLen) == SOCKET_ERROR){\r
+               m_dwLastError = EC_SOCKERROR;\r
+               return FALSE;\r
+               }\r
+\r
+       if(pdwIP)*pdwIP = htonl(LocalAddr.sin_addr.s_addr);\r
+       if(pwPort)*pwPort = ntohs(LocalAddr.sin_port);\r
+\r
+       m_dwLastError = EC_NOERROR;\r
+\r
+       return TRUE;\r
+}\r
+\r
+const BOOL CSmartSock::GetPeerAddr(DWORD *pIP, WORD *pPort)\r
+{\r
+       CHECK_TCPSOCK(FALSE);\r
+\r
+       struct sockaddr_in PeerAddr;\r
+       socklen_t AddrLen = sizeof(PeerAddr);\r
+       \r
+       // \83s\83A\83A\83h\83\8c\83X\8eæ\93¾\r
+       if(::getpeername(m_Socket, (struct sockaddr *)&PeerAddr, &AddrLen) == SOCKET_ERROR){\r
+               m_dwLastError = EC_SOCKERROR;\r
+               return FALSE;\r
+               }\r
+\r
+       if(pIP)*pIP = htonl(PeerAddr.sin_addr.s_addr);\r
+       if(pPort)*pPort = ntohs(PeerAddr.sin_port);\r
+\r
+       m_dwLastError = EC_NOERROR;\r
+\r
+       return TRUE;\r
+}\r
+\r
+const BOOL CSmartSock::Bind()\r
+{\r
+       CHECK_FREESOCK(FALSE);\r
+\r
+       // UDP\83\\83P\83b\83g\8dì\90¬\r
+       if((m_Socket = ::socket(PF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET){\r
+               m_dwLastError = EC_SOCKERROR;\r
+               return FALSE;\r
+               }\r
+\r
+       // \83A\83h\83\8c\83X\90Ý\92è\r
+       SOCKADDR_IN SockAddr;\r
+       SockAddr.sin_family = AF_INET;\r
+       SockAddr.sin_port = 0U;\r
+       SockAddr.sin_addr.s_addr = INADDR_ANY;\r
+\r
+       // \83o\83C\83\93\83h\r
+       if(::bind(m_Socket, (struct sockaddr *)&SockAddr, sizeof(SockAddr)) == SOCKET_ERROR){\r
+               Close();\r
+               m_dwLastError = EC_SOCKERROR;\r
+               return FALSE;\r
+               }\r
+\r
+       m_dwLastError = EC_NOERROR;\r
+       m_bSockType = SOCKTYPE_UDP;\r
+       \r
+       return TRUE;\r
+}\r
+\r
+const DWORD CSmartSock::SendTo(const DWORD dwIP, const WORD wPort, const BYTE *pBuff, const DWORD dwLen)\r
+{\r
+       CHECK_UDPSOCK(0UL);\r
+\r
+       if(!pBuff || !dwLen){\r
+               m_dwLastError = EC_PARAMINVALID;\r
+               return 0UL;\r
+               }\r
+\r
+       // \83A\83h\83\8c\83X\90Ý\92è\r
+       SOCKADDR_IN SockAddr;\r
+       SockAddr.sin_family = AF_INET;\r
+       SockAddr.sin_port = htons(wPort);\r
+       SockAddr.sin_addr.s_addr = htonl(dwIP);\r
+\r
+       // \91\97\90M\r
+       int iSend = sendto(m_Socket, (const char *)pBuff, dwLen, 0, (struct sockaddr *)&SockAddr, sizeof(SockAddr));\r
+       \r
+       if(iSend == SOCKET_ERROR){\r
+               m_dwLastError = EC_SOCKERROR;\r
+               return 0UL;\r
+               }\r
+\r
+       m_dwLastError = EC_NOERROR;\r
+\r
+       return (DWORD)iSend;\r
+}\r
+\r
+const DWORD CSmartSock::SendTo(LPCTSTR lpszHost, const WORD wPort, const BYTE *pBuff, const DWORD dwLen)\r
+{\r
+       CHECK_UDPSOCK(0UL);\r
+\r
+       if(!lpszHost || !pBuff || !dwLen){\r
+               m_dwLastError = EC_PARAMINVALID;\r
+               return 0UL;\r
+               }\r
+               \r
+       // \83A\83h\83\8c\83X\96¼\82©\82çIP\83A\83h\83\8c\83X\8eæ\93¾\r
+       const DWORD dwIP = HostToIP(lpszHost);\r
+\r
+       if(dwIP == INADDR_NONE){\r
+               m_dwLastError = EC_SOCKERROR;\r
+               return 0UL;             \r
+               }\r
+       \r
+       return SendTo(dwIP, wPort, pBuff, dwLen);\r
+}\r
+\r
+const DWORD CSmartSock::RecvFrom(BYTE *pBuff, const DWORD dwLen, DWORD *pdwIP, WORD *pwPort)\r
+{\r
+       CHECK_UDPSOCK(0UL);\r
+\r
+       if(!pBuff || !dwLen){\r
+               m_dwLastError = EC_PARAMINVALID;\r
+               return 0UL;\r
+               }\r
+\r
+       // \83A\83h\83\8c\83X\90Ý\92è\r
+       socklen_t iSockSize = sizeof(SOCKADDR_IN);\r
+       SOCKADDR_IN SockAddr;\r
+       SockAddr.sin_family = AF_INET;\r
+       SockAddr.sin_port = 0U;\r
+       SockAddr.sin_addr.s_addr = 0UL;\r
+\r
+       // \8eó\90M\r
+       const int iRecv = ::recvfrom(m_Socket, (char *)pBuff, dwLen, 0, (struct sockaddr *)&SockAddr, &iSockSize);\r
+\r
+       if(iRecv == SOCKET_ERROR){\r
+               m_dwLastError = EC_SOCKERROR;\r
+               return 0UL;\r
+               }\r
+\r
+       if(pdwIP)*pdwIP = SockAddr.sin_addr.s_addr;\r
+       if(pwPort)*pwPort = ntohs(SockAddr.sin_port);\r
+\r
+       m_dwLastError = EC_NOERROR;\r
+\r
+       return (DWORD)iRecv;\r
+}\r
+\r
+const BOOL CSmartSock::Close()\r
+{\r
+       // \83\\83P\83b\83g\83N\83\8d\81[\83Y\r
+       if(m_Socket != INVALID_SOCKET){\r
+               if(m_bSockType == SOCKTYPE_TCP){\r
+                       char byData;\r
+                       ::shutdown(m_Socket, SD_BOTH);\r
+                       while(::recv(m_Socket, &byData, 1, 0) == 1);\r
+                       }\r
+\r
+               ::close(m_Socket);\r
+               m_Socket = INVALID_SOCKET;\r
+               }\r
+       \r
+       m_bSockType = SOCKTYPE_NON;\r
+       m_dwLastError = EC_NOERROR;\r
+       \r
+       return TRUE;\r
+}\r
+\r
+const DWORD CSmartSock::HostToIP(LPCTSTR lpszHost)\r
+{\r
+#ifdef _UNICODE\r
+       char szHost[1024] = {"\0"};\r
+       ::wcstombs(szHost, lpszHost, sizeof(szHost) - 1);\r
+#else\r
+       LPCSTR szHost = lpszHost;\r
+#endif\r
+\r
+       // \83z\83X\83g\96¼\82©\82çIP\83A\83h\83\8c\83X\8eæ\93¾\r
+       const DWORD dwIP = ::inet_addr(szHost);\r
+\r
+       if(dwIP == INADDR_NONE){\r
+               struct hostent *pHost = ::gethostbyname(szHost);\r
+               if(!pHost){             \r
+                       return INADDR_NONE;\r
+                       }\r
+               else return *((DWORD *)pHost->h_addr_list[0]);\r
+               }\r
+       else return htonl(dwIP);\r
+}\r
+\r
+const DWORD CSmartSock::IPToHost(LPTSTR lpszHost, const DWORD dwIP)\r
+{\r
+       if(!lpszHost)return FALSE;\r
+\r
+       // IP\83A\83h\83\8c\83X\82©\82ç\83z\83X\83g\96¼\8eæ\93¾\r
+       const DWORD dwNetIP = htonl(dwIP);\r
+       struct hostent *pHost = ::gethostbyaddr((const char *)&dwNetIP, sizeof(dwNetIP), AF_INET);\r
+       if(!pHost)return FALSE;\r
+\r
+#ifdef _UNICODE\r
+       ::mbstowcs(lpszHost, pHost->h_name, ::lstrlenA(pHost->h_name));\r
+#else\r
+       ::strcpy(lpszHost, pHost->h_name);\r
+#endif\r
+\r
+       return ::strlen(lpszHost);\r
+}\r
+\r
+const DWORD CSmartSock::GetLastError() const\r
+{\r
+       // \8dÅ\8cã\82É\94­\90\82µ\82½\83G\83\89\81[\82ð\95Ô\82·\r
+       return m_dwLastError;\r
+}\r
+\r
+const BOOL CSmartSock::InitWinSock2(void)\r
+{\r
+#ifdef _UNICODE\r
+       ::setlocale(LC_ALL, "japanese");\r
+#endif\r
+/*\r
+       WSADATA WsaData;\r
+\r
+       // WinSock2\8f\89\8aú\89»\r
+       if(::WSAStartup(MAKEWORD(2, 2), &WsaData))return FALSE;\r
+\r
+       if((LOBYTE(WsaData.wVersion) != 2U) || (HIBYTE(WsaData.wVersion) != 2U))return FALSE;\r
+*/\r
+       return TRUE;\r
+}\r
+\r
+const BOOL CSmartSock::FreeWinSock2(void)\r
+{\r
+/*
+       // WinSock2\8aJ\95ú\r
+       return (::WSACleanup())? TRUE : FALSE;\r
+*/
+       return TRUE;
+}\r
diff --git a/b25-remote/SmartSock.h b/b25-remote/SmartSock.h
new file mode 100755 (executable)
index 0000000..d735339
--- /dev/null
@@ -0,0 +1,79 @@
+// SmartSock.h: CSmartSock \83N\83\89\83X\82Ì\83C\83\93\83^\81[\83t\83F\83C\83X\r
+//\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+#pragma once\r
+\r
+#include "W2L.h"\r
+#include <sys/socket.h>
+#include <fcntl.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <errno.h>
+\r
+#define BOOL bool
+#define LPTSTR char*
+#define LPCTSTR const char*
+#define LPCSTR const char*
+#define BYTE  unsigned char
+#define WORD  unsigned short
+#define DWORD unsigned long
+#define SOCKET int
+\r
+// WinSock2\83^\83C\83\80\83A\83E\83g\91Î\89\9e\83\89\83b\83p\81[\83N\83\89\83X      http://2sen.dip.jp/friio/\r
+class CSmartSock\r
+{\r
+public:\r
+       enum                                    // LastError\83R\81[\83h\r
+       {\r
+               EC_NOERROR,                     // \90³\8fí\8fI\97¹\r
+               EC_SOCKERROR,           // \83\\83P\83b\83g\83G\83\89\81[\r
+               EC_TIMEOUT,                     // \83^\83C\83\80\83A\83E\83g\r
+               EC_SOCKINVALID,         // \83\\83P\83b\83g\82ª\96³\8cø\r
+               EC_PARAMINVALID         // \83p\83\89\83\81\81[\83^\82ª\96³\8cø\r
+       };\r
+\r
+       CSmartSock();\r
+       virtual ~CSmartSock();\r
+\r
+// TCP\83\\83P\83b\83g\r
+       const BOOL Connect(LPCTSTR lpszHost, const WORD wPort, const DWORD dwTimeOut = 0UL);\r
+       const BOOL Connect(const DWORD dwIP, const WORD wPort, const DWORD dwTimeOut = 0UL);\r
+\r
+       const BOOL Listen(const WORD wPort);\r
+       CSmartSock * Accept(void);\r
+\r
+       const BOOL Send(const BYTE *pBuff, const DWORD dwLen, const DWORD dwTimeOut = 0UL);\r
+       const BOOL Recv(BYTE *pBuff, const DWORD dwLen, const DWORD dwTimeOut = 0UL);\r
+       const DWORD SendOnce(const BYTE *pBuff, const DWORD dwMaxLen, const DWORD dwTimeOut = 0UL);\r
+       const DWORD RecvOnce(BYTE *pBuff, const DWORD dwMaxLen, const DWORD dwTimeOut = 0UL);\r
+\r
+       const BOOL GetLocalAddr(DWORD *pdwIP, WORD *pwPort = NULL);\r
+       const BOOL GetPeerAddr(DWORD *pdwIP, WORD *pwPort = NULL);\r
+\r
+// UDP\83\\83P\83b\83g\r
+       const BOOL Bind(void);\r
+\r
+       const DWORD SendTo(const DWORD dwIP, const WORD wPort, const BYTE *pBuff, const DWORD dwLen);\r
+       const DWORD SendTo(LPCTSTR lpszHost, const WORD wPort, const BYTE *pBuff, const DWORD dwLen);\r
+       const DWORD RecvFrom(BYTE *pBuff, const DWORD dwLen, DWORD *pdwIP = NULL, WORD *pwPort = NULL);\r
+\r
+       const BOOL Close(void);\r
+\r
+       static const DWORD HostToIP(LPCTSTR lpszHost);\r
+       static const DWORD IPToHost(LPTSTR lpszHost, const DWORD dwIP);\r
+\r
+       const DWORD GetLastError(void) const;\r
+\r
+protected:\r
+       static const BOOL InitWinSock2(void);\r
+       static const BOOL FreeWinSock2(void);\r
+\r
+       enum {SOCKTYPE_NON, SOCKTYPE_TCP, SOCKTYPE_UDP};\r
+\r
+       int m_Socket;                           // \83\\83P\83b\83g\83n\83\93\83h\83\8b\r
+       BYTE m_bSockType;                               // \83\\83P\83b\83g\83^\83C\83v\r
+       DWORD m_dwLastError;                    // \8dÅ\8fI\83G\83\89\81[\83R\81[\83h\r
+       static DWORD dwInstanceNum;             // \83C\83\93\83X\83^\83\93\83X\82Ì\90\94\r
+};\r
diff --git a/b25-remote/TsUtilClass.cpp b/b25-remote/TsUtilClass.cpp
new file mode 100755 (executable)
index 0000000..ec4c298
--- /dev/null
@@ -0,0 +1,88 @@
+// TsUtilClass.cpp: TS\83\86\81[\83e\83B\83\8a\83e\83B\81[\83N\83\89\83X\82Ì\83C\83\93\83v\83\8a\83\81\83\93\83e\81[\83V\83\87\83\93\r
+//\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+#include "TsUtilClass.h"\r
+\r
+\r
+//////////////////////////////////////////////////////////////////////\r
+// CDynamicReferenceable \83N\83\89\83X\82Ì\8d\\92z/\8fÁ\96Å\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+CDynamicReferenceable::CDynamicReferenceable()\r
+       : m_dwRefCount(0UL)\r
+{\r
+\r
+}\r
+\r
+CDynamicReferenceable::~CDynamicReferenceable()\r
+{\r
+\r
+}\r
+\r
+void CDynamicReferenceable::AddRef(void)\r
+{\r
+       // \8eQ\8fÆ\83J\83E\83\93\83g\83C\83\93\83N\83\8a\83\81\83\93\83g\r
+       m_dwRefCount++;\r
+}\r
+\r
+void CDynamicReferenceable::ReleaseRef(void)\r
+{\r
+       // \8eQ\8fÆ\83J\83E\83\93\83g\83f\83N\83\8a\83\81\83\93\83g\r
+       if(m_dwRefCount){\r
+               // \83C\83\93\83X\83^\83\93\83X\8aJ\95ú\r
+               if(!(--m_dwRefCount))delete this;\r
+               }\r
+#ifdef _DEBUG\r
+       else{\r
+               ::DebugBreak();\r
+               }\r
+#endif\r
+}\r
+\r
+\r
+//////////////////////////////////////////////////////////////////////\r
+// CCriticalLock \83N\83\89\83X\82Ì\8d\\92z/\8fÁ\96Å\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+CCriticalLock::CCriticalLock()\r
+{\r
+       // \83N\83\8a\83e\83B\83J\83\8b\83Z\83N\83V\83\87\83\93\8f\89\8aú\89»\r
+       pthread_mutex_init(&m_CriticalSection, NULL);\r
+}\r
+\r
+CCriticalLock::~CCriticalLock()\r
+{\r
+       // \83N\83\8a\83e\83B\83J\83\8b\83Z\83N\83V\83\87\83\93\8dí\8f\9c\r
+       pthread_mutex_destroy(&m_CriticalSection);\r
+}\r
+\r
+void CCriticalLock::Lock(void)\r
+{\r
+       // \83N\83\8a\83e\83B\83J\83\8b\83Z\83N\83V\83\87\83\93\8eæ\93¾\r
+       pthread_mutex_lock(&m_CriticalSection);\r
+}\r
+\r
+void CCriticalLock::Unlock(void)\r
+{\r
+       // \83N\83\8a\83e\83B\83J\83\8b\83Z\83N\83V\83\87\83\93\8aJ\95ú\r
+       pthread_mutex_unlock(&m_CriticalSection);\r
+}\r
+       \r
+       \r
+//////////////////////////////////////////////////////////////////////\r
+// CBlockLock \83N\83\89\83X\82Ì\8d\\92z/\8fÁ\96Å\r
+//////////////////////////////////////////////////////////////////////\r
+       \r
+CBlockLock::CBlockLock(CCriticalLock *pCriticalLock)\r
+       : m_pCriticalLock(pCriticalLock)\r
+{\r
+       // \83\8d\83b\83N\8eæ\93¾\r
+       m_pCriticalLock->Lock();\r
+}\r
+\r
+CBlockLock::~CBlockLock()\r
+{\r
+       // \83\8d\83b\83N\8aJ\95ú\r
+       m_pCriticalLock->Unlock();\r
+}\r
diff --git a/b25-remote/TsUtilClass.h b/b25-remote/TsUtilClass.h
new file mode 100755 (executable)
index 0000000..ebae86b
--- /dev/null
@@ -0,0 +1,61 @@
+// TsUtilClass.h: TS\83\86\81[\83e\83B\83\8a\83e\83B\81[\83N\83\89\83X\82Ì\83C\83\93\83^\81[\83t\83F\83C\83X\r
+//\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+#pragma once\r
+#include "W2L.h"\r
+#include <pthread.h>
+\r
+#define DWORD unsigned long
+
+/////////////////////////////////////////////////////////////////////////////\r
+// \83_\83C\83i\83~\83b\83N\83\8a\83t\83@\83\8c\83\93\83X\8aÇ\97\9d\83x\81[\83X\83N\83\89\83X\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+class CDynamicReferenceable\r
+{\r
+public:\r
+       CDynamicReferenceable();\r
+       virtual ~CDynamicReferenceable();\r
+\r
+       void AddRef(void);\r
+       void ReleaseRef(void);\r
+\r
+private:\r
+       DWORD m_dwRefCount;\r
+};\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+// \83N\83\8a\83e\83B\83J\83\8b\83Z\83N\83V\83\87\83\93\83\89\83b\83p\81[\83N\83\89\83X\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+class CCriticalLock\r
+{\r
+public:\r
+       CCriticalLock();\r
+       virtual ~CCriticalLock();\r
+       \r
+       void Lock(void);\r
+       void Unlock(void);\r
+       \r
+private:\r
+       pthread_mutex_t m_CriticalSection;\r
+};\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+// \83u\83\8d\83b\83N\83X\83R\81[\83v\83\8d\83b\83N\83N\83\89\83X\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+class CBlockLock\r
+{\r
+public:\r
+       CBlockLock(CCriticalLock *pCriticalLock);\r
+       virtual ~CBlockLock();\r
+               \r
+private:\r
+       CCriticalLock *m_pCriticalLock;\r
+};\r
+\r
+\r
diff --git a/b25-remote/W2L.h b/b25-remote/W2L.h
new file mode 100755 (executable)
index 0000000..678823d
--- /dev/null
@@ -0,0 +1,14 @@
+#include <string.h>
+
+#define TCHAR char
+#define PVOID void*
+#define HANDLE void*
+#define TRUE 1
+#define FALSE 0
+#define INVALID_SOCKET (-1)
+#define SOCKET_ERROR (-1)
+#define SOCKADDR_IN struct sockaddr_in
+#define SOCKADDR struct sockaddr
+#define PSOCKADDR SOCKADDR*
+#define SD_BOTH SHUT_RDWR
+
diff --git a/b25-remote/b25-client.cpp b/b25-remote/b25-client.cpp
new file mode 100755 (executable)
index 0000000..f108e00
--- /dev/null
@@ -0,0 +1,87 @@
+// MllMain.cpp : DLL \83A\83v\83\8a\83P\81[\83V\83\87\83\93\82Ì\83G\83\93\83g\83\8a \83|\83C\83\93\83g\82ð\92è\8b`\82µ\82Ü\82·\81B\r
+//\r
+#include <winscard.h>
+#include <stdio.h>\r
+#include "CasProxy.h"\r
+#include "W2L.h"\r
+#ifndef SCARD_AUTOALLOCATE
+  #define SCARD_AUTOALLOCATE (DWORD)(-1)  /**< see SCardFreeMemory() */
+#endif\r
+
+//////////////////////////////////////////////////////////////////////\r
+// WinSCard\83t\83b\83N\r
+//////////////////////////////////////////////////////////////////////\r
+LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)\r
+{\r
+       // \83v\83\8d\83L\83V\83C\83\93\83X\83^\83\93\83X\90\90¬\r
+       CCasProxy *pCasProxy = new CCasProxy();\r
+
+       // \83T\81[\83o\82É\90Ú\91±\r
+       if(!pCasProxy->Connect()){\r
+               delete pCasProxy;\r
+               *phCard = NULL;\r
+               return SCARD_E_READER_UNAVAILABLE;\r
+               }
+\r
+       // \83n\83\93\83h\83\8b\82É\96\84\82ß\8d\9e\82Þ\r
+       *phCard = reinterpret_cast<SCARDHANDLE>(pCasProxy);\r
+       if(pdwActiveProtocol)*pdwActiveProtocol = SCARD_PROTOCOL_T1;\r
+\r
+       return SCARD_S_SUCCESS;\r
+}\r
+\r
+LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)\r
+{\r
+       // \83T\81[\83o\82©\82ç\90Ø\92f\r
+       CCasProxy *pCasProxy = reinterpret_cast<CCasProxy *>(hCard);\r
+       if(pCasProxy)delete pCasProxy;\r
+\r
+       return SCARD_S_SUCCESS;\r
+}\r
+\r
+LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext)\r
+{
+       return SCARD_S_SUCCESS;\r
+}\r
+\r
+LONG SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem)\r
+{\r
+       return SCARD_S_SUCCESS;\r
+}\r
+\r
+LONG SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders, LPDWORD pcchReaders)\r
+{\r
+       const char szReaderName[] = "BonCasLink Proxy Card Reader\0";\r
+\r
+       if(pcchReaders){\r
+               if((*pcchReaders == SCARD_AUTOALLOCATE) && mszReaders){\r
+                       *((LPCSTR *)mszReaders) = szReaderName;         \r
+                       return SCARD_S_SUCCESS;\r
+                       }\r
+               else{\r
+                       *pcchReaders = sizeof(szReaderName);\r
+                       }\r
+               }\r
+\r
+       if(mszReaders) memcpy(mszReaders, szReaderName, sizeof(szReaderName));\r
+\r
+       return SCARD_S_SUCCESS;\r
+}\r
+\r
+LONG SCardTransmit(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci, LPCBYTE pbSendBuffer, DWORD cbSendLength, LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength)\r
+{\r
+       // \83T\81[\83o\82É\83\8a\83N\83G\83X\83g\91\97\8eó\90M\r
+       CCasProxy *pCasProxy = reinterpret_cast<CCasProxy *>(hCard);\r
+       if(!pCasProxy)return SCARD_E_READER_UNAVAILABLE;\r
+\r
+       DWORD dwRecvLen = pCasProxy->TransmitCommand(pbSendBuffer, cbSendLength, pbRecvBuffer);\r
+       if(pcbRecvLength)*pcbRecvLength = dwRecvLen;\r
+\r
+       return (dwRecvLen)? SCARD_S_SUCCESS : SCARD_E_TIMEOUT;\r
+}\r
+\r
+LONG SCardReleaseContext(SCARDCONTEXT hContext)\r
+{\r
+       return SCARD_S_SUCCESS;\r
+}\r
+
diff --git a/b25-remote/b25-server.cpp b/b25-remote/b25-server.cpp
new file mode 100755 (executable)
index 0000000..674af68
--- /dev/null
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include "CasServer.h"
+
+CCasServer m_CasServer(NULL);
+int m_dwServerPort = 6900UL;
+
+int main() {
+       if(!m_CasServer.OpenServer(m_dwServerPort)){\r
+               printf("サーバの起動に失敗しました。\nTCPポートまたはカードリーダをオープンできません。\n");\r
+               return TRUE;\r
+       }
+       getchar();
+}
+