?? sslserversocket.cpp
字號:
SOCKADDR_IN client;
int iAddrSize=sizeof(client);
m_pSocket = new CSslServerSocket();//用于連接
m_pSocket->m_pList=m_pList;
m_pSocket->m_pObSock=m_pObSock;//公用一個鏈表
m_pSocket->m_type=m_type;
m_pSocket->m_pConnection=m_pConnection;
if(Accept(*m_pSocket,(SOCKADDR *)&client,&iAddrSize))
{
CString str;
str.Format("客戶 %s TCP接入成功,等待握手......",inet_ntoa(client.sin_addr));
m_pList->AddMsg(str,M_WARING);
m_pSocket->m_Ssl = SSL_new (m_Ctx);
SSL_set_accept_state(m_pSocket->m_Ssl);
sbio=BIO_new_socket(m_pSocket->m_hSocket,BIO_NOCLOSE);
SSL_set_bio(m_pSocket->m_Ssl,sbio,sbio);
for(;;)
{
if ((err = SSL_accept (m_pSocket->m_Ssl)) <= 0)
{
if (BIO_sock_should_retry(err))
{
continue;
}
int verify_error=SSL_get_verify_result(m_pSocket->m_Ssl);
if (verify_error != X509_V_OK)//succeeded or no peer certificate was presented
{
sprintf(out,"verify error:%s\n",
X509_verify_cert_error_string(verify_error));
m_pList->AddMsg(out,M_ERROR);
}
else
{
m_pList->AddMsg("客戶端沒有證書,握手結束",M_WARING);
m_pSocket->Close();
delete m_pSocket;
m_pSocket=NULL;
}
return ;
}
else
{
m_pSocket->AsyncSelect(FD_READ|FD_CLOSE);//選擇讀事件(OnReceive)
str.Format("握手結束,客戶%s接入成功",inet_ntoa(client.sin_addr));
GetPeerInfo(m_pSocket->m_Ssl,&m_CLIENTINFO);
m_pList->AddMsg(str,M_WARING);
m_pObSock->AddTail(m_pSocket);
break;
}
}
}
else
{
m_pList->AddMsg("TCP連接失敗",M_ERROR);
m_pSocket->Close();
delete m_pSocket;
m_pSocket=NULL;
}
CAsyncSocket::OnAccept(nErrorCode);
}
void CSslServerSocket::OnClose(int nErrorCode)
{
// TODO: Add your specialized code here and/or call the base class
CString clientIp;
unsigned int port;
POSITION pos;
GetPeerName(clientIp,port);//得到用戶ip,port
clientIp+="已經斷開連接!";
clientIp="客戶"+clientIp;
m_pList->AddMsg(clientIp,M_WARING);
pos=m_pObSock->Find(this);
if(pos) m_pObSock->RemoveAt(pos);//客戶端關閉
if(m_Ssl!=NULL)
{
SSlShouDown();
}
delete this;
CAsyncSocket::OnClose(nErrorCode);
}
int CSslServerSocket::SSlSend(char *buf, int len)
{
if(m_Ssl==NULL)
return -1;
int k=0;//接收數量
int offect=0;//偏移
for(;0!=len;)//maximum record size of 16kB for SSLv3/TLSv1
{
k = SSL_write(m_Ssl,buf+offect,len);
if (k <= 0)
{
if (BIO_sock_should_retry(k))
{
Sleep(100);
continue;//重試
}
return k;//出錯
}
offect+=k;
len-=k;
}
AsyncSelect(FD_READ|FD_CLOSE);
return offect;
}
int CSslServerSocket::SSlReceive(char *buf, int len)
{
int k=0;
do
{
for(;;)
{
k = SSL_read(m_Ssl,buf,len);
if (k <= 0)
{
if (BIO_sock_should_retry(k))
{
Sleep(100);
continue;//重試
}
return k;//錯誤退出
}
break;//成功
}
}while (SSL_pending(m_Ssl));
return k;
}
void CSslServerSocket::DisplayError(_com_error &e)
{
CString msgText;
_bstr_t bstrSource(e.Source());
_bstr_t bstrDescription(e.Description());
msgText.Format("連接數據庫錯誤\n錯誤代碼 = %08lx\n", e.Error());
msgText += " Msg: ";
msgText += e.ErrorMessage();
msgText += "\n 來源: ";
msgText += bstrSource;
msgText += "\n 內容: ";
msgText += bstrDescription;
m_pList->AddMsg(msgText,M_ERROR);
}
void CSslServerSocket::OnReceive(int nErrorCode) //與客戶端交互
{
// TODO: Add your specialized code here and/or call the base class
if(m_type==0)//www
{
char buf[1024]={0};
SSlReceive(buf,1024);
AsyncSelect(FD_WRITE|FD_CLOSE);
}
else//ra
{
stuCA CA;//接收用結構
if(SSlReceive((char *)&CA,sizeof(stuCA))<=0)//對方已經關閉
return;
stuRA RA;//用于發送的結構
_variant_t Affected;//影響行數
_RecordsetPtr m_pRecordset;
m_pRecordset.CreateInstance(_uuidof(Recordset));
switch(CA.Type)
{
case Input://錄入證書
{
stuCERT sCERT;
CString strSQL;
if(SSlReceive((char * )&sCERT,sizeof(sCERT))<0)//接收客戶信息
return;
char * p=(char *)&sCERT;
VARIANT varBLOB;
SAFEARRAY FAR *psa;
SAFEARRAYBOUND rgsabound[1];
SYSTEMTIME tm;
GetLocalTime(&tm);
CString time;
time.Format("%d-%d-%d", tm.wYear,tm.wMonth,tm.wDay);
try
{
if (m_pConnection == NULL)
{
return;
}
m_pRecordset->Open("CERTLIST",_variant_t((IDispatch*)m_pConnection,true),
adOpenDynamic,adLockOptimistic,adCmdTable);//打開表
m_pRecordset->AddNew(); ///添加新記錄
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = sizeof(stuCERT);
psa = SafeArrayCreate(VT_UI1, 1, rgsabound); ///創建SAFEARRAY對象
for (long i =0;i<sizeof(stuCERT); i++)
{
SafeArrayPutElement (psa, &i, p++); ///保存二進制數據
}
// 由于Variant沒有SafeArray的構造函數,所以手工設置Variant的數據類型和值。
varBLOB.vt = VT_ARRAY | VT_UI1;
varBLOB.parray = psa;
m_pRecordset->Fields->GetItem("USERINFO")->AppendChunk(varBLOB); ///加入數據
SafeArrayDestroy(psa);
m_pRecordset->Fields->GetItem("INPUTTIME")->PutValue(_variant_t(time));
_variant_t UserID=m_pRecordset->Fields->GetItem("ID")->Value;//得到id
m_pRecordset->Update(); //更新
RA.ID=UserID.lVal;//ID
RA.Type=Input;//操作類型
RA.State=TRUE;//操作狀態
SSlSend((char *)&RA,sizeof(RA));
}
catch (_com_error &e)
{
DisplayError(e);
RA.Type=Input;//操作類型
RA.State=FALSE;//操作狀態
SSlSend((char *)&RA,sizeof(RA));
}
break;
}
case FInputD://待審核
case FAuditD://待制作
case FMadeD://有效
case FRevokeD://無效
{
try
{
if (m_pConnection == NULL)
{
return;
}
m_pRecordset->Open((_bstr_t)CA.SQL,(IDispatch*)m_pConnection,adOpenStatic,//靜態游標
adLockOptimistic,adCmdText);
m_Rcount=m_pRecordset->RecordCount;//紀錄條數--靜態游標有效
if(!m_pRecordset->adoEOF)//存在紀錄
{
for(int index=0;!m_pRecordset->adoEOF;m_pRecordset->MoveNext(),index++)//遍歷所有記錄
{
//得到用戶ID,個體信息
_variant_t varBLOB;
varBLOB = m_pRecordset->Fields->GetItem("USERINFO")->GetChunk(sizeof(RA.SUBJECT));
if(varBLOB.vt == (VT_ARRAY | VT_UI1))
{
char *pBuf = NULL;
SafeArrayAccessData(varBLOB.parray,(void **)&pBuf);
memcpy(&RA.SUBJECT,pBuf,sizeof(RA.SUBJECT));//個體信息
SafeArrayUnaccessData(varBLOB.parray);
}
_variant_t UserID=m_pRecordset->Fields->GetItem("ID")->Value;
RA.ID=UserID.lVal;//ID
switch(CA.Type)
{
case FInputD://查詢代審核
{
_bstr_t InputTime=m_pRecordset->Fields->GetItem("INPUTTIME")->Value;
CString Input=InputTime.copy();
strcpy(RA.Time,Input);//操作時間
RA.Type=FInputD;//操作類型
RA.State=TRUE;//操作狀態
if(index==0)//第一次發送總紀錄數
{
RA.CertL=m_Rcount;//總紀錄數
RA.KeyL=1;//KeyL=1 -->總紀錄數
}
if(index==m_Rcount-1)//最后一條紀錄(一條紀錄時候m_Rcount=1)
{
RA.CertL=m_Rcount;//總紀錄數
RA.KeyL=-1;
}
if(index!=0&&index!=m_Rcount-1)
{
RA.CertL=index;//其余發送紀錄數
RA.KeyL=0;
}
break;
}
case FAuditD://查詢代制作
{
_bstr_t AuditTime=m_pRecordset->Fields->GetItem("AUDITIME")->Value;
CString Audit=AuditTime.copy();
strcpy(RA.Time,Audit);//操作時間
RA.Type=FAuditD;//操作類型
RA.State=TRUE;//操作狀態
if(index==0)//第一次發送總紀錄數
{
RA.CertL=m_Rcount;//總紀錄數
RA.KeyL=1;//KeyL=1 -->總紀錄數
}
if(index==m_Rcount-1)//最后一條紀錄(一條紀錄時候m_Rcount=1)
{
RA.CertL=m_Rcount;//總紀錄數
RA.KeyL=-1;
}
if(index!=0&&index!=m_Rcount-1)
{
RA.CertL=index;//其余發送紀錄數
RA.KeyL=0;
}
break;
}
case FMadeD://查詢已經制作
{
_bstr_t MadeTime=m_pRecordset->Fields->GetItem("MADETIME")->Value;
CString Made=MadeTime.copy();
strcpy(RA.Time,Made);//操作時間
RA.Type=FMadeD;//操作類型
RA.State=TRUE;//操作狀態
if(index==0)//第一次發送總紀錄數
{
RA.CertL=m_Rcount;//總紀錄數
RA.KeyL=1;//KeyL=1 -->總紀錄數
}
if(index==m_Rcount-1)//最后一條紀錄(一條紀錄時候m_Rcount=1)
{
RA.CertL=m_Rcount;//總紀錄數
RA.KeyL=-1;
}
if(index!=0&&index!=m_Rcount-1)
{
RA.CertL=index;//其余發送紀錄數
RA.KeyL=0;
}
break;
}
case FRevokeD: //查詢已經作廢
{
_bstr_t DelTime=m_pRecordset->Fields->GetItem("REVOKETIME")->Value;
CString Del=DelTime.copy();
strcpy(RA.Time,Del);//操作時間
RA.Type=FRevokeD;//操作類型
RA.State=TRUE;//操作狀態
if(index==0)//第一次發送總紀錄數
{
RA.CertL=m_Rcount;//總紀錄數
RA.KeyL=1;//KeyL=1 -->總紀錄數
}
if(index==m_Rcount-1)//最后一條紀錄(一條紀錄時候m_Rcount=1)
{
RA.CertL=m_Rcount;//總紀錄數
RA.KeyL=-1;
}
if(index!=0&&index!=m_Rcount-1)
{
RA.CertL=index;//其余發送紀錄數
RA.KeyL=0;
}
break;
}
default:
{
m_pList->AddMsg("未知命令",M_ERROR);
break;
}
}
if(SSlSend((char *)&RA,sizeof(RA))<=0)//發送
break;
}
}
else//紀錄為0
{
switch(CA.Type)
{
case FInputD://查詢代審核
{
RA.Type=FInputD;//操作類型
RA.State=TRUE;//操作狀態
RA.KeyL=1;
break;
}
case FAuditD://查詢代制作
{
RA.Type=FAuditD;//操作類型
RA.State=TRUE;//操作狀態
RA.KeyL=1;
break;
}
case FMadeD://查詢已經制作
{
RA.Type=FMadeD;//操作類型
RA.State=TRUE;//操作狀態
RA.KeyL=1;
break;
}
case FRevokeD://查詢已經作廢
{
RA.Type=FRevokeD;//操作類型
RA.State=TRUE;//操作狀態
RA.KeyL=1;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -