bool Session::FlushSend()
{
	if (!IsConnected())
	{
		DisconnectRequest(DR_SENDFLUSH_ERROR);
		return true;
	}
		

	FastSpinlockGuard criticalSection(mSendBufferLock);

	/// 보낼 데이터가 없는 경우
	if (0 == mSendBuffer.GetContiguiousBytes())
	{
		/// 보낼 데이터도 없는 경우
		if (0 == mSendPendingCount)
			return true;
		
		return false;
	}

	/// 이전의 send가 완료 안된 경우
	if (mSendPendingCount > 0)
		return false;

	
	OverlappedSendContext* sendContext = new OverlappedSendContext(this);

	DWORD sendbytes = 0;
	DWORD flags = 0;
	sendContext->mWsaBuf.len = (ULONG)mSendBuffer.GetContiguiousBytes();
	sendContext->mWsaBuf.buf = mSendBuffer.GetBufferStart();

	/// start async send
	if (SOCKET_ERROR == WSASend(mSocket, &sendContext->mWsaBuf, 1, &sendbytes, flags, (LPWSAOVERLAPPED)sendContext, NULL))
	{
		if (WSAGetLastError() != WSA_IO_PENDING)
		{
			DeleteIoContext(sendContext);
			printf_s("Session::FlushSend Error : %d\n", GetLastError());

			DisconnectRequest(DR_SENDFLUSH_ERROR);
			return true;
		}

	}

	mSendPendingCount++;

	return mSendPendingCount == 1;
}
void
BluetoothServiceChildProcess::Disconnect(
  const uint16_t aProfileId,
  BluetoothReplyRunnable* aRunnable)
{
  SendRequest(aRunnable, DisconnectRequest(aProfileId));
}
void
BluetoothServiceChildProcess::Disconnect(
  const BluetoothAddress& aDeviceAddress,
  uint16_t aServiceUuid,
  BluetoothReplyRunnable* aRunnable)
{
  SendRequest(aRunnable, DisconnectRequest(aDeviceAddress, aServiceUuid));
}
void ClientSession::ConnectCompletion()
{
	CRASH_ASSERT( LThreadType == THREAD_IO_WORKER );
	if ( 1 == InterlockedExchange( &mConnected, 1 ) )
	{
		/// already exists?
		CRASH_ASSERT( false );
		return;
	}

	bool resultOk = true;

	do
	{
		if ( SOCKET_ERROR == setsockopt( mSocket, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0 ) )
		{
			printf_s( "[DEBUG] SO_UPDATE_CONNECT_CONTEXT error: %d\n", GetLastError() );
			resultOk = false;
			break;
		}

		int opt = 1;
		if ( NO_DELAY )
		{
			int opt = 1;
			if ( SOCKET_ERROR == setsockopt( mSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&opt, sizeof( int ) ) )
			{
				printf_s( "[DEBUG] TCP_NODELAY error: %d\n", GetLastError() );
				resultOk = false;
				break;
			}
		}

		opt = 0;
		if ( SOCKET_ERROR == setsockopt( mSocket, SOL_SOCKET, SO_RCVBUF, (const char*)&opt, sizeof( int ) ) )
		{
			printf_s( "[DEBUG] SO_RCVBUF change error: %d\n", GetLastError() );
			resultOk = false;
			break;
		}

		int addrlen = sizeof( SOCKADDR_IN );
		if ( SOCKET_ERROR == getpeername( mSocket, (SOCKADDR*)&mClientAddr, &addrlen ) )
		{
			printf_s( "[DEBUG] getpeername error: %d\n", GetLastError() );
			resultOk = false;
			break;
		}

	} while ( false );
	
	if ( !resultOk )
	{
		DisconnectRequest( DR_ONCONNECT_ERROR );
		return;
	}
	
	FastSpinlockGuard criticalSection( mBufferLock );

	if ( BUFFER_SIZE <= 0 || BUFFER_SIZE > BUFSIZE )
	{
		BUFFER_SIZE = 4096;
	}

	char* temp = new char[BUFFER_SIZE];
	
	ZeroMemory( temp, sizeof( char ) * BUFFER_SIZE );
	for ( int i = 0; i < BUFFER_SIZE - 1; ++i )
	{
		temp[i] = 'a' + ( mSocket % 26 );
	}

	temp[BUFFER_SIZE - 1] = '\0';

	char* bufferStart = mBuffer.GetBuffer();
	memcpy( bufferStart, temp, BUFFER_SIZE );

	mBuffer.Commit( BUFFER_SIZE );
		
	CRASH_ASSERT( 0 != mBuffer.GetContiguiousBytes() );
		
	OverlappedSendContext* sendContext = new OverlappedSendContext( this );

	DWORD sendbytes = 0;
	DWORD flags = 0;
	sendContext->mWsaBuf.len = (ULONG)mBuffer.GetContiguiousBytes();
	sendContext->mWsaBuf.buf = mBuffer.GetBufferStart();

	delete[] temp;

	/// start async send
	if ( SOCKET_ERROR == WSASend( mSocket, &sendContext->mWsaBuf, 1, &sendbytes, flags, (LPWSAOVERLAPPED)sendContext, NULL ) )
	{
		if ( WSAGetLastError() != WSA_IO_PENDING )
		{
			DeleteIoContext( sendContext );
			printf_s( "ClientSession::PostSend Error : %d\n", GetLastError() );
		}
	}

	++mUseCount;
}
void RocketTaskbar::Disconnect()
{
    emit DisconnectRequest();
}
RocketTaskbar::RocketTaskbar(Framework *framework, QWidget *observed) :
    QGraphicsProxyWidget(0, Qt::Widget),
    LC("[RocketTaskbar]: "),
    framework_(framework),
    observed_(observed),
    widget_(new QWidget(0)),
    anchor_(Bottom),
    style_(SolidDefault),
    sizePolicy_(QSizePolicy::Minimum),
    loadBarEnabled_(true),
    hideRequested_(false),
    minimumWidth_(0),
    loaderAnimation_(0)
{
    ui_.setupUi(widget_);
    setWidget(widget_);

    loaderAnimation_ = new QMovie(":/images/loader.gif", "GIF", this);
    if (loaderAnimation_->isValid())
    {
        ui_.labelLoader->setMovie(loaderAnimation_);
        loaderAnimation_->setCacheMode(QMovie::CacheAll);
    }

    // Hide loader widgets initially.
    ui_.labelLoader->hide();
    ui_.labelLoaderInfo->hide();
    ui_.frameLoader->hide();
    
    // Prepare toolbar for QActions
    toolBarRight_ = new QToolBar(widget_);
    toolBarRight_->setContentsMargins(0,0,0,0);
    toolBarRight_->setStyleSheet("background-color: none; border: 0px;");
    toolBarRight_->setToolButtonStyle(Qt::ToolButtonIconOnly);
    toolBarRight_->setOrientation(Qt::Horizontal);
    toolBarRight_->setIconSize(QSize(32,32));
    toolBarRight_->setFloatable(false);
    toolBarRight_->setMovable(false);
    toolBarRight_->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);

    QHBoxLayout *lRight = qobject_cast<QHBoxLayout*>(ui_.frameRight->layout());
    if (lRight)
        lRight->addWidget(toolBarRight_);
    
    // Set initial style
    CheckStyleSheets();
    
    // Support "legacy" icons from BrowserUiPlugin, without linking to it, we don't want to fail loading if not present.
    QObject *browserPlugin = framework_->property("browserplugin").value<QObject*>();
    if (browserPlugin)
    {
        connect(browserPlugin, SIGNAL(ActionAddRequest(QAction*, QString)), SLOT(AddAction(QAction*)));
        connect(browserPlugin, SIGNAL(OpenUrlRequest(const QUrl&, bool)), SLOT(OnOpenUrl(const QUrl&)));
    }
    
    resizeDelayTimer_.setSingleShot(true);
    messageHideTimer_.setSingleShot(true);

    // Connections.
    connect(framework_->Ui()->GraphicsScene(), SIGNAL(sceneRectChanged(const QRectF&)), SLOT(OnWindowResized(const QRectF&)));
    connect(&resizeDelayTimer_, SIGNAL(timeout()), SLOT(OnDelayedResize()));
    connect(&messageHideTimer_, SIGNAL(timeout()), SLOT(ClearMessage()));
    connect(ui_.buttonDisconnect, SIGNAL(clicked()), SIGNAL(DisconnectRequest()));
    
    // Add ourselves to the scene.
    framework_->Ui()->GraphicsScene()->addItem(this);
    hide();
}
void ClientSession::AcceptCompletion()
{
	// for test
	// TRACE_PERF;
	TRACE_THIS;

	CRASH_ASSERT(LThreadType == THREAD_IO_WORKER);
	
	if (1 == InterlockedExchange(&mConnected, 1))
	{
		/// already exists?
		CRASH_ASSERT(false);
		return;
	}

	bool resultOk = true;
	do 
	{
		if (SOCKET_ERROR == setsockopt(mSocket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char*)GIocpManager->GetListenSocket(), sizeof(SOCKET)))
		{
			printf_s("[DEBUG] SO_UPDATE_ACCEPT_CONTEXT error: %d\n", GetLastError());
			resultOk = false;
			break;
		}

		int opt = 1;
		if (SOCKET_ERROR == setsockopt(mSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&opt, sizeof(int)))
		{
			printf_s("[DEBUG] TCP_NODELAY error: %d\n", GetLastError());
			resultOk = false;
			break;
		}

		opt = 0;
		if (SOCKET_ERROR == setsockopt(mSocket, SOL_SOCKET, SO_RCVBUF, (const char*)&opt, sizeof(int)))
		{
			printf_s("[DEBUG] SO_RCVBUF change error: %d\n", GetLastError());
			resultOk = false;
			break;
		}

		int addrlen = sizeof(SOCKADDR_IN);
		if (SOCKET_ERROR == getpeername(mSocket, (SOCKADDR*)&mClientAddr, &addrlen))
		{
			printf_s("[DEBUG] getpeername error: %d\n", GetLastError());
			resultOk = false;
			break;
		}

		HANDLE handle = CreateIoCompletionPort((HANDLE)mSocket, GIocpManager->GetComletionPort(), (ULONG_PTR)this, 0);
		if (handle != GIocpManager->GetComletionPort())
		{
			printf_s("[DEBUG] CreateIoCompletionPort error: %d\n", GetLastError());
			resultOk = false;
			break;
		}

	} while (false);


	if (!resultOk)
	{
		DisconnectRequest(DR_ONCONNECT_ERROR);
		return;
	}

	printf_s("[DEBUG] Client Connected: IP=%s, PORT=%d\n", inet_ntoa(mClientAddr.sin_addr), ntohs(mClientAddr.sin_port));

	if (false == PreRecv())
	{
		printf_s("[DEBUG] PreRecv error: %d\n", GetLastError());
	}


	//TEST: 요놈의 위치는 원래 C_LOGIN 핸들링 할 때 해야하는거지만 지금은 접속 완료 시점에서 테스트 ㄱㄱ

	//todo: 플레이어 id는 여러분의 플레이어 테이블 상황에 맞게 적절히 고쳐서 로딩하도록 
	static int id = 101;
	mPlayer.TestCreatePlayerData( L"testName" );
	mPlayer.RequestLoad( id++ );
	mPlayer.TestDeletePlayerData( id );
	// DONE
}
void ClientSession::ConnectCompletion()
{
	CRASH_ASSERT(LThreadType == THREAD_IO_WORKER);
	
	if (1 == InterlockedExchange(&mConnected, 1))
	{
		/// already exists?
		CRASH_ASSERT(false);
		return;
	}

	bool resultOk = true;
	do 
	{
		if ( SOCKET_ERROR == setsockopt( mSocket, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0 ))
		{
			printf_s("[DEBUG] SO_UPDATE_ACCEPT_CONTEXT error: %d\n", GetLastError());
			resultOk = false;
			break;
		}
		/*
		int opt = 1;
		if (SOCKET_ERROR == setsockopt(mSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&opt, sizeof(int)))
		{
			printf_s("[DEBUG] TCP_NODELAY error: %d\n", GetLastError());
			resultOk = false;
			break;
		}

		opt = 0;
		if (SOCKET_ERROR == setsockopt(mSocket, SOL_SOCKET, SO_RCVBUF, (const char*)&opt, sizeof(int)))
		{
			printf_s("[DEBUG] SO_RCVBUF change error: %d\n", GetLastError());
			resultOk = false;
			break;
		}

		int addrlen = sizeof(SOCKADDR_IN);
		if (SOCKET_ERROR == getpeername(mSocket, (SOCKADDR*)&mClientAddr, &addrlen))
		{
			printf_s("[DEBUG] getpeername error: %d\n", GetLastError());
			resultOk = false;
			break;
		}

		HANDLE handle = CreateIoCompletionPort((HANDLE)mSocket, GIocpManager->GetComletionPort(), (ULONG_PTR)this, 0);
		if (handle != GIocpManager->GetComletionPort())
		{
			printf_s("[DEBUG] CreateIoCompletionPort error: %d\n", GetLastError());
			resultOk = false;
			break;
		}
		*/
	} while (false);


	if (!resultOk)
	{
		DisconnectRequest(DR_ONCONNECT_ERROR);
		return;
	}

	printf_s("[DEBUG] Client Connected: IP=%s, PORT=%d\n", inet_ntoa(mClientAddr.sin_addr), ntohs(mClientAddr.sin_port));

	if (false == PreSend())
	{
		printf_s("[DEBUG] PreSend error: %d\n", GetLastError());
	}

	/// 타이머 테스트를 위해 10ms 후에 player 가동 ㄱㄱ
	//DoSyncAfter(10, mPlayer, &Player::Start, 1000);
}