/** * Socket associated with client connection has indicated it has data ready * to read. We want to determine which client connection and receive the data * from it. */ void Server::handleServerConnection(int sckt) { //determine connection ServerConnection* connection = mConnections->getServerConnection(sckt); if (0 != connection) { Callback* callback = getCallback(); try { //receive data std::vector<char> result = connection->performReceive(); if (0 != callback) { callback->receiveComplete(connection->getIdentifier(), &(result[0]), result.size()); } } catch (std::runtime_error) { if (0 != callback) { callback->disconnected(connection->getIdentifier()); } //error retrieving data from client, connection is bad, need to remove it mConnections->removeServerConnection(sckt); } } }
EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) { EGLWrapperContext *wctx = (EGLWrapperContext *)ctx; EGLContext aglContext = (ctx == EGL_NO_CONTEXT ? EGL_NO_CONTEXT : wctx->aglContext); EGLThreadInfo *ti = getEGLThreadInfo(); EGLBoolean res = getDispatch()->eglMakeCurrent(dpy, draw, read, aglContext); if (res ) { // NOTE - we do get a pointer to the server connection, (rather then using ti->serverConn) // for cases that this is the first egl call of the current thread. ServerConnection *server; if (s_needEncode && (server = ServerConnection::s_getServerConnection())) { server->utEnc()->makeCurrentContext(server->utEnc(), getpid(), (uint32_t) (draw == EGL_NO_SURFACE ? 0 : draw), (uint32_t) (read == EGL_NO_SURFACE ? 0 : read), (uint32_t) (ctx == EGL_NO_CONTEXT ? 0 : ctx)); server->glEncoder()->setClientState( wctx ? wctx->clientState : NULL ); server->gl2Encoder()->setClientState( wctx ? wctx->clientState : NULL ); } // set current context in our thread info ti->currentContext = wctx; } return res; }
// FreeQueryIterator void ServerVolume::FreeQueryIterator(QueryIterator* _iterator) { ServerQueryIterator* iterator = dynamic_cast<ServerQueryIterator*>(_iterator); int32 cookie = iterator->GetRemoteCookie(); if (cookie >= 0) { // prepare the close request CloseRequest request; request.volumeID = -1; request.cookie = cookie; // send the request ServerConnection* serverConnection = fConnectionProvider->GetExistingServerConnection(); if (serverConnection && serverConnection->IsConnected()) { CloseReply* reply; status_t error = SendRequest( serverConnection->GetRequestConnection(), &request, &reply); if (error == B_OK) delete reply; } } delete iterator; }
void ServerConnection::StaticConnectCallback(AsyncOpPtr theOp, RefCountPtr theParam) { PeerAuthOp *anOp = (PeerAuthOp*)theOp.get(); ServerConnection *thisConnection = (ServerConnection*)theParam.get(); thisConnection->ConnectCallback(anOp); }
// ReadQuery status_t ServerVolume::ReadQuery(QueryIterator* _iterator, struct dirent* buffer, size_t bufferSize, int32 count, int32* countRead) { // get connection ServerConnection* serverConnection = fConnectionProvider->GetExistingServerConnection(); if (!serverConnection) return ERROR_NOT_CONNECTED; RequestConnection* connection = serverConnection->GetRequestConnection(); ServerQueryIterator* iterator = dynamic_cast<ServerQueryIterator*>(_iterator); *countRead = 0; for (;;) { // if the iterator hasn't cached any more share volume IDs, we need to // ask the server for the next entry if (!iterator->HasNextShareVolumeID()) { // prepare the request ReadQueryRequest request; request.cookie = iterator->GetRemoteCookie(); request.count = 1; // send the request ReadQueryReply* reply; status_t error = SendRequest(connection, &request, &reply); if (error != B_OK) RETURN_ERROR(error); ObjectDeleter<Request> replyDeleter(reply); if (reply->error != B_OK) RETURN_ERROR(reply->error); // check, if anything has been read at all if (reply->count == 0) { *countRead = 0; return B_OK; } // update the iterator error = iterator->SetEntry(reply->clientVolumeIDs.GetElements(), reply->clientVolumeIDs.CountElements(), reply->dirInfo, reply->entryInfo); if (error != B_OK) return error; } // get the next concerned share volume and delegate the rest of the work int32 volumeID = iterator->NextShareVolumeID(); ShareVolume* shareVolume = _GetShareVolume(volumeID); if (!shareVolume) continue; VolumePutter volumePutter(shareVolume); return shareVolume->GetQueryEntry(iterator->GetEntryInfo(), iterator->GetDirectoryInfo(), buffer, bufferSize, countRead); } }
void ServerConnection::StaticMsgCallback(AsyncOpPtr theOp, RefCountPtr theParam) { RecvMsgOp *anOp = (RecvMsgOp*)theOp.get(); ServerConnection *thisConnection = (ServerConnection*)theParam.get(); if(anOp->GetStatus()==WS_Success) thisConnection->MsgCallback(anOp->GetMsg()); }
void ServerConnection::threadFn(void *arg) { ServerConnection *me = (ServerConnection*)arg; me->threadFn(); delete me; }
EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) { ServerConnection *server; if (s_needEncode && (server = ServerConnection::s_getServerConnection()) != NULL) { server->utEnc()->swapBuffers(server->utEnc(), getpid(), (uint32_t)surface); server->glEncoder()->flush(); server->gl2Encoder()->flush(); return 1; } return getDispatch()->eglSwapBuffers(dpy, surface); }
EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) { EGLBoolean res = getDispatch()->eglDestroySurface(dpy, surface); if (res && surface != EGL_NO_SURFACE) { ServerConnection *server; if (s_needEncode && (server = ServerConnection::s_getServerConnection()) != NULL) { server->utEnc()->destroySurface(server->utEnc(), getpid(), (uint32_t)surface); } } return res; }
EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list) { EGLSurface surface = getDispatch()->eglCreatePixmapSurface(dpy, config, pixmap, attrib_list); if (surface != EGL_NO_SURFACE) { ServerConnection *server; if (s_needEncode && (server = ServerConnection::s_getServerConnection()) != NULL) { server->utEnc()->createSurface(server->utEnc(), getpid(), (uint32_t)surface); } } return surface; }
void Server::incomingConnection(int socketDescriptor) { qDebug() << "Server: incoming connection"; QMutexLocker lock(&m_serverPropMutex); ServerConnection* connection = new ServerConnection(socketDescriptor, m_lossless, m_maxFramesInQueue, m_maxFramesInFlight); connection->setAcknowledgeNeeded(m_acknowledge); lock.unlock(); // let errors go through the error reporting signal of this class connect( this, SIGNAL( onError(PlvErrorType,QString)), connection, SIGNAL(onError(PlvErrorType,QString))); // move the connection to its own thread QThreadEx* connectionThread = new QThreadEx(); connection->moveToThread(connectionThread); // when the connection is done it is scheduled for deletion connect( connection, SIGNAL(finished()), connection, SLOT(deleteLater())); // when the connection is done, it stops its thread connect( connection, SIGNAL(finished()), connectionThread, SLOT(quit())); // start the connection when its thread is started connect( connectionThread, SIGNAL(started()), connection, SLOT(start())); // inform server when this serverthead is waiting on the client connect( connection, SIGNAL( waitingOnClient(ServerConnection*,bool)), this, SLOT( serverThreadStalled(ServerConnection*,bool)) ); connect( parent(), SIGNAL( maxFramesInQueueChanged(int) ), connection, SLOT( setMaxFramesInQueue(int) ) ); //setMaxFrameInQueue &&maxFrameInQueueChanged added in TODO check connect( parent(), SIGNAL( maxFramesInFlightChanged(int) ), connection, SLOT( setMaxFramesInFlight(int)) ); connect( parent(), SIGNAL( losslessChanged(bool) ), connection, SLOT( setLossless(bool)) ); // stop this connection when stopAllConnections is called connect( this, SIGNAL(stopAllConnections()), connection, SLOT(stop())); // start the connection thread and its event loop connectionThread->start(); // connection receives all broadcasts and sends it to its connection connect( this, SIGNAL( broadcastFrame(quint32,QByteArray)), connection, SLOT( queueFrame(quint32,QByteArray))); }
void ProgramSettingsDialog::on_addConnectionButton_clicked() { AddServerDialog d(this); if (d.exec()) { ServerConnection c = d.getConnection(); if (c.createWorker(this)) { c.worker->incRef(); m_connections.append(c); ui->connectionList->addItem(c.toString()); } } refresh(); }
void heartbeatThread(ServerConnection& conn) { std::chrono::seconds beatTime{5}; std::chrono::seconds reconnTime{30}; while(!conn.closed()) { if (!conn.connected()) { std::this_thread::sleep_for(reconnTime); conn.connect(); } else { std::this_thread::sleep_for(beatTime); conn.heartbeat(); } } }
ServerConnection* ServerManager::min() { if (conns_.empty()) return NULL; ServerConnection* conn = NULL; std::vector<ServerConnection*>::iterator it = conns_.begin(); for (; it != conns_.end(); ++it) { if (conn == NULL || (*it)->get_conns() < conn->get_conns()) conn = *it; } return conn; }
// OpenQuery status_t ServerVolume::OpenQuery(const char* queryString, uint32 flags, port_id port, int32 token, QueryIterator** _iterator) { // TODO: Do nothing when there are no (mounted) shares. // get connection ServerConnection* serverConnection = fConnectionProvider->GetExistingServerConnection(); if (!serverConnection) return ERROR_NOT_CONNECTED; RequestConnection* connection = serverConnection->GetRequestConnection(); // create a query iterator and add it to the query manager ServerQueryIterator* iterator = new(std::nothrow) ServerQueryIterator(this); if (!iterator) return B_NO_MEMORY; QueryManager* queryManager = fVolumeManager->GetQueryManager(); status_t error = queryManager->AddIterator(iterator); if (error != B_OK) { delete iterator; return error; } QueryIteratorPutter iteratorPutter(queryManager, iterator); // prepare the request OpenQueryRequest request; request.queryString.SetTo(queryString); request.flags = flags; request.port = port; request.token = token; // send the request OpenQueryReply* reply; error = SendRequest(connection, &request, &reply); if (error != B_OK) RETURN_ERROR(error); ObjectDeleter<Request> replyDeleter(reply); if (reply->error != B_OK) RETURN_ERROR(reply->error); // set the result iterator->SetRemoteCookie(reply->cookie); *_iterator = iterator; iteratorPutter.Detach(); return B_OK; }
EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list) { EGLContext share = share_context; if (share) share = ((EGLWrapperContext *)share_context)->aglContext; // check if are ES2, and convert it to ES1. int nAttribs = 0; if (attrib_list != NULL) { while(attrib_list[nAttribs] != EGL_NONE) { nAttribs++; } nAttribs++; } EGLint *attrib = NULL; if (nAttribs > 0) { attrib = new EGLint[nAttribs]; memcpy(attrib, attrib_list, nAttribs * sizeof(EGLint)); } int version = 1; for (int i = 0; i < nAttribs; i++) { if (attrib[i] == EGL_CONTEXT_CLIENT_VERSION && attrib[i + 1] == 2) { version = 2; attrib[i + 1] = 1; // replace to version 1 } } EGLContext ctx = getDispatch()->eglCreateContext(dpy, config, share, attrib); delete attrib; EGLWrapperContext *wctx = new EGLWrapperContext(ctx, version); if (ctx != EGL_NO_CONTEXT) { ServerConnection *server; if (s_needEncode && (server = ServerConnection::s_getServerConnection()) != NULL) { wctx->clientState = new GLClientState(); server->utEnc()->createContext(server->utEnc(), getpid(), (uint32_t)wctx, (uint32_t)(share_context == EGL_NO_CONTEXT ? 0 : share_context), wctx->version); } } return (EGLContext)wctx; }
bool ManagerTimer::transfer(ClientConnection* client) { ServerConnection* server; const char* peer; char buf[256]; int ret; // 从服务端连接管理对象中取得连接数最小的一个 // 服务端对象,并将所给客户端连接传递给它, // 一直到成功或所有传输都失败为止 while (true) { server = ServerManager::get_instance().min(); if (server == NULL) { logger_error("no server available for client: %s", client->get_peer()); return false; } peer = client->get_peer(); if (peer == NULL) peer = "unkonwn"; memset(buf, 0, sizeof(buf)); snprintf(buf, sizeof(buf), "%s", peer); // 将客户端连接传递给服务端,如果失败,则尝试下一个 // 服务端,同时将失败的服务端从服务端管理集合中删除 ret = acl_write_fd(server->sock_handle(), buf, strlen(buf), client->sock_handle()); if (ret == -1) { logger_error("write fd to backend error: %s", acl::last_serror()); ServerManager::get_instance().del(server); server->close(); } else server->inc_nconns(); return true; } }
EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) { EGLWrapperContext *wctx = (EGLWrapperContext *)ctx; EGLBoolean res = EGL_FALSE; if (ctx && ctx != EGL_NO_CONTEXT) { res = getDispatch()->eglDestroyContext(dpy, wctx->aglContext); if (res) { EGLThreadInfo *ti = getEGLThreadInfo(); ServerConnection *server; if (s_needEncode && (server = ServerConnection::s_getServerConnection())) { server->utEnc()->destroyContext(ti->serverConn->utEnc(), getpid(), (uint32_t)ctx); } if (ti->currentContext == wctx) ti->currentContext = NULL; delete wctx; } } return res; }
void Server::incomingConnection(int socketDescriptor) { qDebug() << "Server: incoming connection"; ServerConnection* connection = new ServerConnection(socketDescriptor); // let errors go through the error reporting signal of this class this->connect( connection, SIGNAL(errorOccurred(PipelineErrorType,QString)), SIGNAL(error(PipelineErrorType,QString))); // move the connection to its own thread QThreadEx* connectionThread = new QThreadEx(); connection->moveToThread(connectionThread); // when the connection is done it is scheduled for deletion connect( connection, SIGNAL(finished()), connection, SLOT(deleteLater())); // when the connection is done, it stops its thread connect( connection, SIGNAL(finished()), connectionThread, SLOT(quit())); // start the connection when its thread is started connect( connectionThread, SIGNAL(started()), connection, SLOT(start())); // inform server when this serverthead is waiting on the client connect( connection, SIGNAL( waitingOnClient(ServerConnection*,bool)), this, SLOT( serverThreadStalled(ServerConnection*,bool)) ); // stop this connection when stopAllConnections is called connect( this, SIGNAL(stopAllConnections()), connection, SLOT(stop())); // start the connection thread and its event loop connectionThread->start(); // connection receives all broadcasts and sends it to its connection connect( this, SIGNAL( broadcastFrame(quint32,QByteArray)), connection, SLOT( queueFrame(quint32,QByteArray))); }
// There is a new connection, server sends newConnection signal to me. void MyServer::newConnection() { bool change = false; while(1) { QTcpSocket *socket = server->nextPendingConnection(); if(socket == NULL) break; change = true; ServerConnection *con = new ServerConnection(socket, this); listMutex.lock(); connections.append(con); listMutex.unlock(); emit outMessage(QString("Connection from: ") + con->str()); } if(change) { emit connectionsChanged(); } }
ServerConnection *ScreateServerConnection(int port, int clientNum){ static const int BLACK = GetColor(0, 0, 0); static const int WHITE = GetColor(0, 0, 0); ServerConnection *result = new ServerConnection(port); result->startListen(); while(result->getClientNum() < clientNum){ result->getClientNum(); DrawBox(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, BLACK, 1); DrawFormatString(60, 60, WHITE, "access: %d", result->getClientNum()); ScreenFlip(); Sleep(10); if( ProcessMessage() < 0 ) break ; if( CheckHitKey( KEY_INPUT_ESCAPE ) ){ return NULL; } } result->endListen(); return result; }
void Server::waitForEvents() throw (std::runtime_error) { //setup file descriptors fd_set masterRead; fd_set readFds; fd_set writeFds; FD_ZERO(&masterRead); FD_SET(mWakeupPipe[0], &masterRead); FD_SET(mConnectSocket->getSocket(), &masterRead); mConnections = new Connections(masterRead); int serverMax = std::max(mWakeupPipe[0], mConnectSocket->getSocket()); while (!mHasBeenShutdown) { int numfds = 0; int fdmax = std::max(serverMax, mConnections->getMax()); FD_ZERO(&readFds); FD_ZERO(&writeFds); //copy our master list of file descriptors readFds = masterRead; writeFds = mMasterWrite; /** * Select from specified file descriptors, will block */ numfds = select(fdmax + 1, &readFds, &writeFds, NULL, 0); if (-1 == numfds) { std::stringstream sstr; sstr << "select error " << strerror(errno); throw(std::runtime_error(sstr.str())); } if (mHasBeenShutdown) break; /** * Check all the file descriptors to see which were hit */ for (int i = 0; i <= fdmax; ++i) { if (FD_ISSET(i, &readFds)) //handle reads { /** * If connectSocket is ready, that means a connection is formed, any other * socket (per client connection) shows data is ready to be ready from a * client */ if (i == mConnectSocket->getSocket()) { //handle new connection try { ServerConnection* client = new ServerConnection( mConnectSocket->getSocket()); //performs accept, gets identifier getCallback()->connected(client->getIdentifier()); mConnections->addServerConnection(client); } catch (std::runtime_error& ex) { //TODO: log connection failure //std::cout << "failure: " << ex.what() << std::endl; } } else { //creating a new connection to a client handleServerConnection(i); } } /** * Self-pipe technique to wakeup and add additional file descriptors * to select set. */ if (FD_ISSET(mWakeupPipe[0], &readFds)) //performing wakeup { char buffer[1]; ::recv(mWakeupPipe[0], &mBuffer, sizeof(mBuffer), 0); } /** * See if we're ready to write to a client connection */ if (FD_ISSET(i, &writeFds)) { //ready for write ServerConnection* connection = mConnections->getServerConnection( i); if (0 != connection) { connection->sendQueuedMessage(getCallback()); } //write complete, clear it from the select list FD_CLR(i, &mMasterWrite); } } } }
void ServerConnection::StaticKeepAliveCallback(AsyncOpPtr theOp, RefCountPtr theParam) { ServerConnection *thisConnection = (ServerConnection*)theParam.get(); thisConnection->KeepAliveCallback(theOp); }