inline void poolWorkerOnEnd(uv_work_t* handler, int status) { auto workerData = static_cast<typename PoolWorker<WorkReturn>::WorkerData*>(handler->data); if(handler->data != nullptr && status != UV_ECANCELED) { workerData->onEnd(PoolWorkerOpStatus::Success, std::move(workerData->workReturn)); } else { workerData->onEnd(PoolWorkerOpStatus::WorkCancelled, WorkReturn{}); } delete workerData; delete handler; }
/** * Principal function. It creates Nodes and Edges to put in the Graph, * from the given BBHG * @param bhg source BBHG */ void BBHGDrawer::make() { if(_made) { return; } ASSERT(_bhg); ASSERT(_graph); // Construct the Graph HashTable<void*, display::Node*> map; for(BBHG::Iterator bb(_bhg); bb; bb++) { display::Node *node = _graph->newNode(); map.put(*bb, node); onNode(*bb, node); } for(BBHG::Iterator bb(_bhg); bb; bb++) { display::Node *node = map.get(*bb); for(BBHG::OutIterator succ(bb); succ; succ++) { BBHGEdge* edge = succ; display::Edge *display_edge; display_edge = _graph->newEdge(node,map.get(edge->target())); onEdge(edge, display_edge); } } onEnd(_graph); _made = true; }
/// Called when the animation is updating /// \return MUST return the remaining time not used by the animation /// This is essential as in a play list of animations, when one finished, the next updates immediately. float AnimationGroupSequential::onUpdate(float elapsedTime){ if(getStatus() == AnimationStates::Stopped) return elapsedTime; //PRINTLOG("sf", "TIME: %f\n", elapsedTime); while((elapsedTime > 0.f) && (m_index < m_animations.size())){ elapsedTime -= m_animations[m_index]->onUpdate(elapsedTime); if(m_animations[m_index]->getStatus() == AnimationStates::Stopped){ m_index++; if(m_index < m_animations.size()){ m_animations[m_index]->setStatus(AnimationStates::Playing); m_animations[m_index]->onBegin(); } else{ // Nothing else to play now setStatus(AnimationStates::Stopped); onEnd(); } } } return std::max<float>(elapsedTime, 0.f); };
FlatButton::FlatButton(const QString &text, QWidget *parent) : ButtonWidget(parent), _opacity(this), _eff(this), _hover(this) { setText(text); setFont(QFont(_st.font_family, _st.font_size)); _eff.setStartValue(float(_st.height)); _hover.setStartValue(float(_st.fill_opacity * 2)); _eff.setTimer(15); _hover.setTimer(15); _opacity.setTimer(12); QObject::connect(&_opacity, SIGNAL(ended()), this, SLOT(onEnd())); }
// Called by the client to initiate processing void EntitySystem::update() { if (checkProcessing()) { if (_firstUpdate) onFirstUpdate(); onBegin(); processEntities(_entities); onEnd(); } }
WindowMain::WindowMain(QWidget *parent) : QMainWindow(parent), m_ui(new Ui::WindowMain) { /** Initialize the UI */ m_ui->setupUi(this); /** Set the window title */ setWindowTitle(PACKAGE_STRING); /** Connect the actions */ connect(m_ui->actionAboutQt, SIGNAL(triggered()), qApp, SLOT(aboutQt())); connect(m_ui->actionAbout, SIGNAL(triggered()), this, SLOT(onAbout())); connect(m_ui->actionSettings, SIGNAL(triggered()), this, SLOT(onSettings())); connect(m_ui->actionQuit, SIGNAL(triggered()), this, SLOT(close())); connect(this, SIGNAL(next()), this, SLOT(onNext())); connect(this, SIGNAL(done()), this, SLOT(onEnd())); /** Initialize the settings */ m_settings = new Settings(this); /** Create and setup the drop area */ m_dropArea = new DropArea(); connect(m_dropArea, SIGNAL(dropped(QList<QUrl>)), this, SLOT(onStart(QList<QUrl>))); setCentralWidget(m_dropArea); /** Initialize the status bar */ m_ui->statusBar->setStyleSheet("QStatusBar::item {border: none;}"); m_ui->statusBar->showMessage(tr("Ready")); /** Create the progress bar */ m_progress = new QProgressBar(); /** Create the allocine engine */ m_allocine = new AllocineEngine(); connect(m_allocine, SIGNAL(found(QList<AllocineResult*>)), this, SLOT(onFound(QList<AllocineResult*>))); connect(m_allocine, SIGNAL(fetched(AllocineResult*)), this, SLOT(onFetched(AllocineResult*))); connect(m_allocine, SIGNAL(error(QString)), this, SLOT(onError(QString))); /** Initialize the processing flag */ m_processing = false; }
bool ConditionEffect::onUpdate(Creature* creature, const ConditionEffect& addEffect) { if(type != addEffect.type){ return false; } onEnd(creature, CONDITIONEND_UPDATE); data = addEffect.data; interval = addEffect.interval; return onBegin(creature); }
void TextInput::onUp() { if(m_historyIter == m_history.begin()) m_historyIter++; if(m_historyIter != m_history.end()) { m_value = *(m_historyIter++); setValue(); onEnd(); } }
void processTasks() { cocos2d::CCLog("==HTTP Started"); std::unique_lock<std::mutex> lock(_cond_mutex); while(true) { startTasks(); int still_running = 0; curl_multi_perform(cm, &still_running); int msgs_left = 0; CURLMsg *msg=NULL; while ((msg = curl_multi_info_read(cm, &msgs_left))) { if (msg->msg == CURLMSG_DONE) { CURL* curl = msg->easy_handle; CURLcode return_code = msg->data.result; onEnd(curl, return_code); } else { fprintf(stderr, "error: after curl_multi_info_read(), CURLMsg=%d\n", msg->msg); } } int old_running = getRunning(); startTasks(); int new_running = getRunning(); if(!still_running && new_running == 0) { cocos2d::CCLog("==HTTP sleep"); _cond.wait(lock); cocos2d::CCLog("==HTTP wakeup"); if(stop) return; } if(still_running && old_running == new_running) { int numfds=0; curl_multi_wait(cm, NULL, 0, 1000, &numfds); } } }
void cParser::parse(void) { m_bEnd = false; m_varLine = 0; m_curLine = 0; m_errorID = 0; while(!m_strText.empty() && !m_bEnd) { char ch = m_strText[0]; m_strText = m_strText.substr(1); switch(ch) { case '{' : onLBraket(); break; case '}' : onRBraket(); break; case '=' : onEqual(); break; case '\n' : onReturn(); break; case ' ' : case '\t': onSpace(); break; case '#' : onComment(); break; case ';': break; default: onOther(ch); break; } if (error()) { onError(); } } onEnd(); }
Presenter::Presenter(IView *view) { this->view = view; this->game = new GameController(); QObject* qview = dynamic_cast<QObject*>(view); connect(qview, SIGNAL(onNewGame()), this->game, SLOT(onNewGame())); connect(qview, SIGNAL(onPause()), this->game, SLOT(onPause())); connect(qview, SIGNAL(onRotate()), this->game, SLOT(onRotate())); connect(qview, SIGNAL(onToLeft()), this->game, SLOT(onMoveLeft())); connect(qview, SIGNAL(onToRight()), this->game, SLOT(onMoveRight())); connect(qview, SIGNAL(onSpeedup()), this->game, SLOT(onSpeedup())); connect(qview, SIGNAL(onEndGame()), this->game, SLOT(onEnd())); connect(game, SIGNAL(onStateChanged()), this, SLOT(StateChange())); connect(game, SIGNAL(onGameEnd()), this, SLOT(EndGame())); // instead of speedup connect(qview, SIGNAL(onMakeMove()), this->game, SLOT(onMove())); }
void Timer::run() { while (m_running) { std::unique_lock<std::mutex> lock(m_mutex); // Wait the timer delay or the interrupt m_condition.wait_for(lock, std::chrono::milliseconds(m_delay), [&] () { return m_running == false; }); if (m_running) { // Signal process onSignal(); if (m_type == TimerType::Single) { m_running = false; } } } // Finished onEnd(); }
bool AnimationClip::update(float elapsedTime) { if (isClipStateBitSet(CLIP_IS_PAUSED_BIT)) { return false; } else if (isClipStateBitSet(CLIP_IS_MARKED_FOR_REMOVAL_BIT)) { // If the marked for removal bit is set, it means stop() was called on the AnimationClip at some point // after the last update call. Reset the flag, and return true so the AnimationClip is removed from the // running clips on the AnimationController. onEnd(); return true; } else if (!isClipStateBitSet(CLIP_IS_STARTED_BIT)) { onBegin(); } else { _elapsedTime += elapsedTime * _speed; if (_repeatCount == REPEAT_INDEFINITE && _elapsedTime <= 0) _elapsedTime = _activeDuration + _elapsedTime; } float currentTime = 0.0f; // Check to see if clip is complete. if (_repeatCount != REPEAT_INDEFINITE && ((_speed >= 0.0f && _elapsedTime >= _activeDuration) || (_speed <= 0.0f && _elapsedTime <= 0.0f))) { resetClipStateBit(CLIP_IS_STARTED_BIT); if (_speed >= 0.0f) { // If _duration == 0, we have a "pose". Just set currentTime to 0. if (_duration == 0) { currentTime = 0.0f; } else { currentTime = (float)(_activeDuration % _duration); // Get's the fractional part of the final repeat. if (currentTime == 0.0f) currentTime = _duration; } } else { currentTime = 0.0f; // If we are negative speed, the end value should be 0. } } else { // If _duration == 0, we have a "pose". Just set currentTime to 0. if (_duration == 0) currentTime = 0.0f; else // Gets portion/fraction of the repeat. currentTime = fmodf(_elapsedTime, _duration); } // Notify any listeners of Animation events. if (_listeners) { GP_ASSERT(_listenerItr); if (_speed >= 0.0f) { while (*_listenerItr != _listeners->end() && _elapsedTime >= (long) (**_listenerItr)->_eventTime) { GP_ASSERT(_listenerItr); GP_ASSERT(**_listenerItr); GP_ASSERT((**_listenerItr)->_listener); (**_listenerItr)->_listener->animationEvent(this, Listener::TIME); ++*_listenerItr; } } else { while (*_listenerItr != _listeners->begin() && _elapsedTime <= (long) (**_listenerItr)->_eventTime) { GP_ASSERT(_listenerItr); GP_ASSERT(**_listenerItr); GP_ASSERT((**_listenerItr)->_listener); (**_listenerItr)->_listener->animationEvent(this, Listener::TIME); --*_listenerItr; } } } // Add back in start time, and divide by the total animation's duration to get the actual percentage complete GP_ASSERT(_animation); // If the animation duration is zero (start time == end time, such as when there is only a single keyframe), // then prevent a divide by zero and set percentComplete = 1. float percentComplete = _animation->_duration == 0 ? 1 : ((float)_startTime + currentTime) / (float)_animation->_duration; percentComplete = MATH_CLAMP(percentComplete, 0.0f, 1.0f); if (isClipStateBitSet(CLIP_IS_FADING_OUT_BIT)) { GP_ASSERT(_crossFadeToClip); GP_ASSERT(_crossFadeOutDuration > 0); if (isClipStateBitSet(CLIP_IS_FADING_OUT_STARTED_BIT)) // Calculate elapsed time since the fade out begin. { GP_ASSERT(_crossFadeToClip); _crossFadeOutElapsed = (Game::getGameTime() - _crossFadeToClip->_timeStarted) * fabs(_speed); resetClipStateBit(CLIP_IS_FADING_OUT_STARTED_BIT); } else { // continue tracking elapsed time. _crossFadeOutElapsed += elapsedTime * fabs(_speed); } if (_crossFadeOutElapsed < _crossFadeOutDuration) { // Calculate this clip's blend weight. float tempBlendWeight = ((float)_crossFadeOutDuration - _crossFadeOutElapsed) / (float)_crossFadeOutDuration; // If this clip is fading in, adjust the crossfade clip's weight to be a percentage of your current blend weight if (isClipStateBitSet(CLIP_IS_FADING_IN_BIT)) { _crossFadeToClip->_blendWeight = (1.0f - tempBlendWeight) * _blendWeight; _blendWeight -= _crossFadeToClip->_blendWeight; } else { // Just set the blend weight. _crossFadeToClip->_blendWeight = (1.0f - tempBlendWeight); _blendWeight = tempBlendWeight; } } else { // Fade is done. _crossFadeToClip->_blendWeight = 1.0f; _blendWeight = 0.0f; resetClipStateBit(CLIP_IS_STARTED_BIT); resetClipStateBit(CLIP_IS_FADING_OUT_BIT); _crossFadeToClip->resetClipStateBit(CLIP_IS_FADING_IN_BIT); SAFE_RELEASE(_crossFadeToClip); } } // Evaluate this clip. Animation::Channel* channel = NULL; AnimationValue* value = NULL; AnimationTarget* target = NULL; size_t channelCount = _animation->_channels.size(); for (size_t i = 0; i < channelCount; i++) { channel = _animation->_channels[i]; GP_ASSERT(channel); target = channel->_target; GP_ASSERT(target); value = _values[i]; GP_ASSERT(value); // Evaluate the point on Curve GP_ASSERT(channel->getCurve()); channel->getCurve()->evaluate(percentComplete, value->_value); // Set the animation value on the target property. target->setAnimationPropertyValue(channel->_propertyId, value, _blendWeight); } // When ended. Probably should move to it's own method so we can call it when the clip is ended early. if (isClipStateBitSet(CLIP_IS_MARKED_FOR_REMOVAL_BIT) || !isClipStateBitSet(CLIP_IS_STARTED_BIT)) { onEnd(); return true; } return false; }
void ScreenGame::initialize( GfxEngine& engine, GuiEnv& gui ) { _d->gui = &gui; _d->engine = &engine; _d->infoBoxMgr = InfoBoxManager::create( &gui ); CityPtr city = _d->scenario->getCity(); _d->gui->clear(); /*new PopupMessageBox( _d->gui->getRootWidget(), "Test title", "This is test string for popup message box", "Sen 351 BC", "For New player" ); */ const int topMenuHeight = 23; const Picture& rPanelPic = Picture::load( ResourceGroup::panelBackground, 14 ); Rect rPanelRect( engine.getScreenWidth() - rPanelPic.getWidth(), topMenuHeight, engine.getScreenWidth(), engine.getScreenHeight() ); _d->rightPanel = MenuRigthPanel::create( gui.getRootWidget(), rPanelRect, rPanelPic); _d->topMenu = TopMenu::create( gui.getRootWidget(), topMenuHeight ); _d->topMenu->setPopulation( city->getPopulation() ); _d->topMenu->setFunds( city->getFunds().getValue() ); _d->topMenu->setDate( GameDate::current() ); _d->menu = Menu::create( gui.getRootWidget(), -1, _d->scenario->getCity() ); _d->menu->setPosition( Point( engine.getScreenWidth() - _d->menu->getWidth() - _d->rightPanel->getWidth(), _d->topMenu->getHeight() ) ); _d->extMenu = ExtentMenu::create( gui.getRootWidget(), _d->mapRenderer, -1, _d->scenario->getCity() ); _d->extMenu->setPosition( Point( engine.getScreenWidth() - _d->extMenu->getWidth() - _d->rightPanel->getWidth(), _d->topMenu->getHeight() ) ); _d->wndStackMsgs = WindowMessageStack::create( gui.getRootWidget(), -1 ); _d->wndStackMsgs->setPosition( Point( gui.getRootWidget()->getWidth() / 4, 33 ) ); _d->wndStackMsgs->sendToBack(); _d->rightPanel->bringToFront(); // 8*30: used for high buildings (granary...), visible even when not in tilemap_area. getMapArea().setViewSize( engine.getScreenSize() + Size( 180 ) ); // here move camera to start position of map getMapArea().setCenterIJ( _d->scenario->getCity()->getCameraPos() ); new SenatePopupInfo( _d->gui->getRootWidget(), _d->mapRenderer ); //connect elements CONNECT( _d->topMenu, onSave(), _d.data(), Impl::showSaveDialog ); CONNECT( _d->topMenu, onExit(), this, ScreenGame::resolveExitGame ); CONNECT( _d->topMenu, onEnd(), this, ScreenGame::resolveEndGame ); CONNECT( _d->topMenu, onRequestAdvisor(), _d.data(), Impl::showAdvisorsWindow ); CONNECT( _d->menu, onCreateConstruction(), _d.data(), Impl::resolveCreateConstruction ); CONNECT( _d->menu, onRemoveTool(), _d.data(), Impl::resolveRemoveTool ); CONNECT( _d->menu, onMaximize(), _d->extMenu, ExtentMenu::maximize ); CONNECT( _d->extMenu, onCreateConstruction(), _d.data(), Impl::resolveCreateConstruction ); CONNECT( _d->extMenu, onRemoveTool(), _d.data(), Impl::resolveRemoveTool ); CONNECT( city, onPopulationChanged(), _d->topMenu, TopMenu::setPopulation ); CONNECT( city, onFundsChanged(), _d->topMenu, TopMenu::setFunds ); CONNECT( &GameDate::instance(), onMonthChanged(), _d->topMenu, TopMenu::setDate ); CONNECT( &_d->mapRenderer, onShowTileInfo(), _d.data(), Impl::showTileInfo ); CONNECT( city, onWarningMessage(), _d->wndStackMsgs, WindowMessageStack::addMessage ); CONNECT( &_d->mapRenderer, onWarningMessage(), _d->wndStackMsgs, WindowMessageStack::addMessage ); CONNECT( _d->extMenu, onSelectOverlayType(), _d.data(), Impl::resolveSelectOverlayView ); CONNECT( _d->extMenu, onEmpireMapShow(), _d.data(), Impl::showEmpireMapWindow ); CONNECT( _d->extMenu, onAdvisorsWindowShow(), _d.data(), Impl::showAdvisorsWindow ); CONNECT( _d->extMenu, onMissionTargetsWindowShow(), _d.data(), Impl::showMissionTaretsWindow ); CONNECT( city, onDisasterEvent(), &_d->alarmsHolder, AlarmEventHolder::add ); CONNECT( _d->extMenu, onSwitchAlarm(), &_d->alarmsHolder, AlarmEventHolder::next ); CONNECT( &_d->alarmsHolder, onMoveToAlarm(), &_d->mapArea, TilemapArea::setCenterIJ ); CONNECT( &_d->alarmsHolder, onAlarmChange(), _d->extMenu, ExtentMenu::setAlarmEnabled ); }
bool AnimationClip::update(float elapsedTime) { if (isClipStateBitSet(CLIP_IS_PAUSED_BIT)) { return false; } if (isClipStateBitSet(CLIP_IS_MARKED_FOR_REMOVAL_BIT)) { // If the marked for removal bit is set, it means stop() was called on the AnimationClip at some point // after the last update call. Reset the flag, and return true so the AnimationClip is removed from the // running clips on the AnimationController. onEnd(); return true; } if (!isClipStateBitSet(CLIP_IS_STARTED_BIT)) { // Clip is just starting onBegin(); } else { // Clip was already running _elapsedTime += elapsedTime * _speed; if (_repeatCount == REPEAT_INDEFINITE && _elapsedTime <= 0) { // Elapsed time is moving backwards, so wrap it back around the end when it falls below zero _elapsedTime = _activeDuration + _elapsedTime; // TODO: account for _loopBlendTime } } // Current time within a loop of the clip float currentTime = 0.0f; // Check to see if clip is complete. if (_repeatCount != REPEAT_INDEFINITE && ((_speed >= 0.0f && _elapsedTime >= _activeDuration) || (_speed <= 0.0f && _elapsedTime <= 0.0f))) { // We finished our active duration (including repeats), so clamp to our end value. resetClipStateBit(CLIP_IS_STARTED_BIT); // Ensure we end off at the endpoints of our clip (-speed==0, +speed==_duration) currentTime = _speed < 0.0f ? 0.0f : _duration; } else { // If _duration == 0, we have a "pose". Just set currentTime to 0. if (_duration == 0) { currentTime = 0.0f; } else { // Animation is running normally. currentTime = fmodf(_elapsedTime, _duration + _loopBlendTime); } } // Notify any listeners of Animation events. if (_listeners) { GP_ASSERT(_listenerItr); if (_speed >= 0.0f) { while (*_listenerItr != _listeners->end() && _elapsedTime >= (long) (**_listenerItr)->_eventTime) { GP_ASSERT(_listenerItr); GP_ASSERT(**_listenerItr); GP_ASSERT((**_listenerItr)->_listener); (**_listenerItr)->_listener->animationEvent(this, Listener::TIME); ++*_listenerItr; } } else { while (*_listenerItr != _listeners->begin() && _elapsedTime <= (long) (**_listenerItr)->_eventTime) { GP_ASSERT(_listenerItr); GP_ASSERT(**_listenerItr); GP_ASSERT((**_listenerItr)->_listener); (**_listenerItr)->_listener->animationEvent(this, Listener::TIME); --*_listenerItr; } } } // Add back in start time, and divide by the total animation's duration to get the actual percentage complete GP_ASSERT(_animation); // Compute percentage complete for the current loop (prevent a divide by zero if _duration==0). // Note that we don't use (currentTime/(_duration+_loopBlendTime)). That's because we want a // % value that is outside the 0-1 range for loop smoothing/blending purposes. float percentComplete = _duration == 0 ? 1 : currentTime / (float)_duration; if (_loopBlendTime == 0.0f) percentComplete = MATH_CLAMP(percentComplete, 0.0f, 1.0f); // If we're cross fading, compute blend weights if (isClipStateBitSet(CLIP_IS_FADING_OUT_BIT)) { GP_ASSERT(_crossFadeToClip); GP_ASSERT(_crossFadeOutDuration > 0); if (isClipStateBitSet(CLIP_IS_FADING_OUT_STARTED_BIT)) // Calculate elapsed time since the fade out begin. { GP_ASSERT(_crossFadeToClip); _crossFadeOutElapsed = (Game::getGameTime() - _crossFadeToClip->_timeStarted) * fabs(_speed); resetClipStateBit(CLIP_IS_FADING_OUT_STARTED_BIT); } else { // continue tracking elapsed time. _crossFadeOutElapsed += elapsedTime * fabs(_speed); } if (_crossFadeOutElapsed < _crossFadeOutDuration) { // Calculate this clip's blend weight. float tempBlendWeight = ((float)_crossFadeOutDuration - _crossFadeOutElapsed) / (float)_crossFadeOutDuration; // If this clip is fading in, adjust the crossfade clip's weight to be a percentage of your current blend weight if (isClipStateBitSet(CLIP_IS_FADING_IN_BIT)) { _crossFadeToClip->_blendWeight = (1.0f - tempBlendWeight) * _blendWeight; _blendWeight -= _crossFadeToClip->_blendWeight; } else { // Just set the blend weight. _crossFadeToClip->_blendWeight = (1.0f - tempBlendWeight); _blendWeight = tempBlendWeight; } } else { // Fade is done. _crossFadeToClip->_blendWeight = 1.0f; _blendWeight = 0.0f; resetClipStateBit(CLIP_IS_STARTED_BIT); resetClipStateBit(CLIP_IS_FADING_OUT_BIT); _crossFadeToClip->resetClipStateBit(CLIP_IS_FADING_IN_BIT); SAFE_RELEASE(_crossFadeToClip); } } // Evaluate this clip. Animation::Channel* channel = NULL; AnimationValue* value = NULL; AnimationTarget* target = NULL; size_t channelCount = _animation->_channels.size(); float percentageStart = (float)_startTime / (float)_animation->_duration; float percentageEnd = (float)_endTime / (float)_animation->_duration; float percentageBlend = (float)_loopBlendTime / (float)_animation->_duration; for (size_t i = 0; i < channelCount; i++) { channel = _animation->_channels[i]; GP_ASSERT(channel); target = channel->_target; GP_ASSERT(target); value = _values[i]; GP_ASSERT(value); // Evaluate the point on Curve GP_ASSERT(channel->getCurve()); channel->getCurve()->evaluate(percentComplete, percentageStart, percentageEnd, percentageBlend, value->_value); // Set the animation value on the target property. target->setAnimationPropertyValue(channel->_propertyId, value, _blendWeight); } // When ended. Probably should move to it's own method so we can call it when the clip is ended early. if (isClipStateBitSet(CLIP_IS_MARKED_FOR_REMOVAL_BIT) || !isClipStateBitSet(CLIP_IS_STARTED_BIT)) { onEnd(); return true; } return false; }
void Level::end() { onEnd(); KILLME_DISCONNECT_EVENT_HOOKS(); }
void Manip::onEnd(Real x, Real y, bool canceled) { onEnd(Point(x, y), canceled); }
bool HTTPSocket<isServer>::upgrade(const char *secKey, const char *extensions, size_t extensionsLength, const char *subprotocol, size_t subprotocolLength) { if (isServer) { unsigned char shaInput[] = "XXXXXXXXXXXXXXXXXXXXXXXX258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; memcpy(shaInput, secKey, 24); unsigned char shaDigest[SHA_DIGEST_LENGTH]; SHA1(shaInput, sizeof(shaInput) - 1, shaDigest); char upgradeBuffer[1024]; memcpy(upgradeBuffer, "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: ", 97); base64(shaDigest, upgradeBuffer + 97); memcpy(upgradeBuffer + 125, "\r\n", 2); size_t upgradeResponseLength = 127; if (extensionsLength) { memcpy(upgradeBuffer + upgradeResponseLength, "Sec-WebSocket-Extensions: ", 26); memcpy(upgradeBuffer + upgradeResponseLength + 26, extensions, extensionsLength); memcpy(upgradeBuffer + upgradeResponseLength + 26 + extensionsLength, "\r\n", 2); upgradeResponseLength += 26 + extensionsLength + 2; } if (subprotocolLength) { memcpy(upgradeBuffer + upgradeResponseLength, "Sec-WebSocket-Protocol: ", 24); memcpy(upgradeBuffer + upgradeResponseLength + 24, subprotocol, subprotocolLength); memcpy(upgradeBuffer + upgradeResponseLength + 24 + subprotocolLength, "\r\n", 2); upgradeResponseLength += 24 + subprotocolLength + 2; } static char stamp[] = "Sec-WebSocket-Version: 13\r\nServer: uWebSockets\r\n\r\n"; memcpy(upgradeBuffer + upgradeResponseLength, stamp, sizeof(stamp) - 1); upgradeResponseLength += sizeof(stamp) - 1; uS::SocketData::Queue::Message *messagePtr = allocMessage(upgradeResponseLength, upgradeBuffer); bool wasTransferred; if (write(messagePtr, wasTransferred)) { if (!wasTransferred) { freeMessage(messagePtr); } else { messagePtr->callback = nullptr; } } else { onEnd(*this); return false; } } else { std::string upgradeHeaderBuffer = std::string("GET /") + getData()->path + " HTTP/1.1\r\n" "Upgrade: websocket\r\n" "Connection: Upgrade\r\n" "Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==\r\n" "Host: " + getData()->host + "\r\n" "Sec-WebSocket-Version: 13\r\n\r\n"; uS::SocketData::Queue::Message *messagePtr = allocMessage(upgradeHeaderBuffer.length(), upgradeHeaderBuffer.data()); bool wasTransferred; if (write(messagePtr, wasTransferred)) { if (!wasTransferred) { freeMessage(messagePtr); } else { messagePtr->callback = nullptr; } } else { onEnd(*this); return false; } } return true; }