void VirtuinoEsp8266_WebServer::wifiRun(){ if(espSerial->available()){ char c=espSerial->read(); commandBuffer.concat(c); if (c=='\n') { // check command line to line if (DEBUG) Serial.print(commandBuffer); int pos = commandBuffer.indexOf("+IPD,"); if (pos>=0){ // check for GET command from Virtuino app clearESP_buffer(500); int connectionId = commandBuffer.charAt(pos+5)-48; // get connection ID if (DEBUG) Serial.println("ID="+ String(connectionId)); pos = commandBuffer.indexOf("GET /"); if (pos!=-1){ // We have a GET message String responce = checkNetworkCommand(commandBuffer.substring(pos+5)); boolean b=wifiSendData(connectionId,responce); // ----------- Close client connection ------------- clearESP_buffer(100); closeClientConnection(connectionId); } } commandBuffer=""; // clear buffer for the next line } } }
void ScriptEngineServer::stop() { try { _stopServer = true; GD::bl->threadManager.join(_mainThread); _out.printDebug("Debug: Waiting for script engine server's client threads to finish."); { std::lock_guard<std::mutex> stateGuard(_stateMutex); for(std::map<int32_t, std::shared_ptr<ClientData>>::iterator i = _clients.begin(); i != _clients.end(); ++i) { closeClientConnection(i->second); } } while(_clients.size() > 0) { collectGarbage(); if(_clients.size() > 0) std::this_thread::sleep_for(std::chrono::milliseconds(100)); } unlink(GD::socketPath.c_str()); } catch(const std::exception& ex) { _out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what()); } catch(BaseLib::Exception& ex) { _out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what()); } catch(...) { _out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__); } }
static void sendResponse(EXTENSION_CONTROL_BLOCK *p, HTTPResponse *resp) { String *resphdrs; char status[128]; int browserStatus = 0; DWORD len; p->dwHttpStatusCode = resp->status; sprintf(status, "%d %s",resp->status, resp->statusMsg); /* * send the headers (collected into one buffer) */ resphdrs = resp_packageHeaders(resp); if (resphdrs) { len = resphdrs->length; /* ccording to the Microsoft web site, HSE_REQ_SEND_RESPONSE_HEADER is depreciated */ /* HSE_REQ_SEND_RESPONSE_HEADER_EX is preferred. */ /* However, moving to HSE_REQ_SEND_RESPONSE_HEADER_EX will not work if we must support IIS 3.0. */ if (p->ServerSupportFunction(p->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, status, &len, (LPDWORD)resphdrs->text) != TRUE) { browserStatus = -1; WOLog(WO_ERR,"Failed to send response headers (%d)", GetLastError()); } else { len = 2; // 2009/06/10: The 4th. parameter is only allowed to be '0' if // this code would belong to a filter plugin. But // this code realizes an IIS extension and therefore // only HSE_IO_SYNC and ..._ASYNC is allowed! if (p->WriteClient(p->ConnID, CRLF, &len, HSE_IO_SYNC) != TRUE) { browserStatus = -1; WOLog(WO_ERR,"Failed to send \\r\\n (%d)", GetLastError()); } /* resp->content_valid will be 0 for HEAD requests and empty responses */ if (resp->content_valid) { long count; while (resp->content_read < resp->content_length && (resp->flags & RESP_LENGTH_INVALID) != RESP_LENGTH_INVALID && browserStatus == 0) { len = resp->content_valid; // 2009/06/10: The 4th. parameter is only allowed to be '0' if // this code would belong to a filter plugin. But // this code realizes an IIS extension and therefore // only HSE_IO_SYNC and ..._ASYNC is allowed! if (len && (p->WriteClient(p->ConnID, resp->content, &len, HSE_IO_SYNC) != TRUE)) { browserStatus = -1; WOLog(WO_ERR,"Failed to send content (%d)", GetLastError()); } if(browserStatus == 0) { // read next response chunk from the WebObjects application count = resp_getResponseContent(resp, 1); if(count > 0) { // 2009/06/09: handle situations where content_length is wrong or // unset. Read as much data as possible from the // WebObjects application and send the data to the // client-side. resp->content_read += count; resp->content_valid = count; } if(count != 0) { // 2009/04/30: error while reading response content (this can happen // if the instance dies during sending the response - e.g. // during a file download - or if the content_length is // wrong/unset). Stop the loop to avoid endless looping! WOLog(WO_WARN, "sendResponse(): received an incomplete data package. Please look for a dead instance or adjust content-length value."); } } } if(browserStatus == 0) { len = resp->content_valid; // 2009/06/10: The 4th. parameter is only allowed to be '0' if // this code would belong to a filter plugin. But // this code realizes an IIS extension and therefore // only HSE_IO_SYNC and ..._ASYNC is allowed! if (len && (p->WriteClient(p->ConnID, resp->content, &len, HSE_IO_SYNC) != TRUE)) { browserStatus = -1; WOLog(WO_ERR,"Failed to send content (%d)", GetLastError()); } } } } str_free(resphdrs); } /* else? return warning */ if(resp->content_read < resp->content_length) { // 2009/06/08: in case of an unset/wrong content length value, we // must close the client socket connection to signalize // the client application the end-of-stream. closeClientConnection(p, resp); if(resp->keepConnection != 0) { // 2009/04/30: it is possible, that the user (=browser) cancels the last started // request. The existing mechanism of the nbsocket.c implementation // (starting a reset operation that cleans/consumes the remaining // content of the socket buffer) fails sometimes in such situations. // E.g. during an huge file download, the reset operation doesn't consume // the complete download stream (such a behaviour would be very expensive!), // but only the local socket buffer. If such a connection is reused // in another request-response-cycle, the adaptor/browser gets unexpected // data garbage. This can lead to situations, where the adaptor marks an // existing and fully functional instance as death. Therefore: dump // such connections! WOLog(WO_INFO, "Forget the existing connection."); resp->keepConnection = 0; resp->flags |= RESP_CLOSE_CONNECTION; // after calling the resp_free function, the connection doesn't longer exist! } } return; }
void ScriptEngineServer::readClient(std::shared_ptr<ClientData> clientData) { try { int32_t bufferMax = 1024; char buffer[bufferMax + 1]; std::shared_ptr<std::vector<char>> packet(new std::vector<char>()); int32_t bytesRead; _out.printDebug("Debug: Listening for incoming commands from client number " + std::to_string(clientData->fileDescriptor->id) + "."); while(!_stopServer) { //Timeout needs to be set every time, so don't put it outside of the while loop timeval timeout; timeout.tv_sec = 2; timeout.tv_usec = 0; fd_set readFileDescriptor; FD_ZERO(&readFileDescriptor); GD::bl->fileDescriptorManager.lock(); int32_t nfds = clientData->fileDescriptor->descriptor + 1; if(nfds <= 0) { GD::bl->fileDescriptorManager.unlock(); _out.printDebug("Connection to client number " + std::to_string(clientData->fileDescriptor->id) + " closed."); closeClientConnection(clientData); return; } FD_SET(clientData->fileDescriptor->descriptor, &readFileDescriptor); GD::bl->fileDescriptorManager.unlock(); bytesRead = select(nfds, &readFileDescriptor, NULL, NULL, &timeout); if(bytesRead == 0) continue; if(bytesRead != 1) { _out.printDebug("Connection to client number " + std::to_string(clientData->fileDescriptor->id) + " closed."); closeClientConnection(clientData); return; } bytesRead = read(clientData->fileDescriptor->descriptor, buffer, bufferMax); if(bytesRead <= 0) { _out.printDebug("Connection to client number " + std::to_string(clientData->fileDescriptor->id) + " closed."); closeClientConnection(clientData); //If we close the socket, the socket file gets deleted. We don't want that //GD::bl->fileDescriptorManager.close(_serverFileDescriptor); return; } std::string command; command.insert(command.end(), buffer, buffer + bytesRead); //handleCommand(command, clientData); } closeClientConnection(clientData); } catch(const std::exception& ex) { _out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what()); } catch(BaseLib::Exception& ex) { _out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what()); } catch(...) { _out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__); } }