#include "StdAfx.h"
#include "sslsocket.h"
#include "openssl\err.h"

CSSLSocket::CSSLSocket(CSSLContext *context)
{
	m_context = context;
	m_sslUsing = 0;
}

CSSLSocket::~CSSLSocket(void)
{
	Close();

	SCOPE_LOCK();

	//	SSLデータ開放
	if(m_sslUsing)
	{
		m_sslUsing = 0;

		SSL_shutdown(m_ssl);
		SSL_free(m_ssl);
	}

	//	このスレッドのエラー情報を破棄する
	ERR_remove_state(0);
}

//	切断
void CSSLSocket::Close()
{
	//	ソケットを閉じる
	CMySocket::Close();

	//	Closeを実行したスレッドのエラー情報を破棄する
	ERR_remove_state(0);
}

//	ハンドルから接続開始
int CSSLSocket::SetHandle(SOCKET sock)
{
	//	CMySocketに関連付け
	return CMySocket::SetHandle(sock);
}


//	SSL接続のネゴシエーション
int CSSLSocket::SSLAccept()
{
	SCOPE_LOCK();

	//	ソケットセットアップ
	m_bio=BIO_new_socket((int)m_socket,BIO_NOCLOSE);
	if(m_bio == NULL)
		return(-1);

	m_ssl=SSL_new(m_context->GetCTX());
	if(m_ssl == NULL)
		return(-1);

	SSL_set_bio(m_ssl,m_bio,m_bio);

	m_sslUsing = 1;

	//	ネゴシエーション
	if(SSL_accept(m_ssl)<=0)
		return(-1);

	return(0);
}



//	送信
int CSSLSocket::_send(SOCKET s,char *buf,int len,int flags)
{
	SCOPE_LOCK();

	//	SSL使用中？
	if(!m_sslUsing)
		return(-1);

	int offset=0,mlen = len;

	while(len)
	{
		int r=SSL_write(m_ssl,buf+offset,len);
		switch(SSL_get_error(m_ssl,r))
		{
			case SSL_ERROR_NONE:
				len-=r;
				offset+=r;
				break;

			default:
				return -1;
		}
	}

	return mlen;
}

//	受信
int CSSLSocket::_recv(SOCKET s,char *buf,int len,int flags)
{
	SCOPE_LOCK();

	//	SSL使用中？
	if(!m_sslUsing)
		return(-1);

	return SSL_read(m_ssl,buf,len);
}

//	受信可能？
int CSSLSocket::RecvDataPending(int timeOut)
{
	SCOPE_LOCK();

	//	SSL使用中？
	if(!m_sslUsing)
		return(0);

	//	SSLバッファ内にデータあり？
	if(SSL_pending(m_ssl))
		return(1);

	return(CMySocket::RecvDataPending(timeOut));
}

