void CMessageTemplate::processMacro( LPCSTR str, int len, int fill, IWriteSink & f ) { if ( FarSF::LStricmp( str, M_SUBJECT ) == 0 ) processSubject( len, fill, f ); else if ( FarSF::LStricmp( str, M_FROM ) == 0 ) processFrom( len, fill, f ); else if ( FarSF::LStricmp( str, M_TO ) == 0 ) processTo( len, fill, f ); else if ( FarSF::LStricmp( str, M_DATE ) == 0 ) processDate( len, fill, f ); else if ( FarSF::LStricmp( str, M_ORGANIZATION ) == 0 ) processOrganization( len, fill, f ); else if ( FarSF::LStricmp( str, M_MAILER ) == 0 ) processMailer( len, fill, f ); else if ( FarSF::LStricmp( str, M_OSUBJECT ) == 0 ) processOSubject( len, fill, f ); else if ( FarSF::LStricmp( str, M_MESSAGEID ) == 0 ) processMessageId( len, fill, f ); else if ( FarSF::LStricmp( str, M_FROM_NAME ) == 0 ) processFromName( len, fill, f ); else if ( FarSF::LStricmp( str, M_FROM_ADDR ) == 0 ) processFromAddr( len, fill, f ); else if ( FarSF::LStricmp( str, M_TO_NAME ) == 0 ) processToName( len, fill, f ); else if ( FarSF::LStricmp( str, M_TO_ADDR ) == 0 ) processToAddr( len, fill, f ); else if ( FarSF::LStricmp( str, M_SENT_DATE ) == 0 ) processSentDate( len, fill, f ); else if ( FarSF::LStricmp( str, M_SENT_TIME ) == 0 ) processSentTime( len, fill, f ); else if ( FarSF::LStricmp( str, M_RECEIVED_DATE ) == 0 ) processReceivedDate( len, fill, f ); else if ( FarSF::LStricmp( str, M_RECEIVED_TIME ) == 0 ) processReceivedTime( len, fill, f ); else if ( FarSF::LStricmp( str, M_TEXT ) == 0 ) processText( len, f ); else if ( FarSF::LStricmp( str, M_HEADERS ) == 0 ) processHeaders( f ); else if ( FarSF::LStrnicmp( str, M_KLUDGE, strlen(M_KLUDGE) ) == 0 ) { str += _countof(M_KLUDGE); while ( *str && ( isspace( (unsigned char)*str ) || *str == '(' || *str == '\"' || *str == '\'' ) ) str ++; if ( *str ) { LPCSTR end = str + 1; while ( *end && !isspace( (unsigned char)*end ) && *end != ')' && *end != '\"' && *end != '\'' ) end ++; processKludge( FarString( str, end - str ), f ); } } }
boolean CmdProcessor::processLine(){ //do a simple check to see if it looks like json if(input_buffer_pos > 0 && input_buffer[0] == '{' && input_buffer[input_buffer_pos - 1] == '}'){ socketMode = RAW; processJSON(); return true; }else if(processHeaders()){ return true; } if(httpState == WEBSOCKET_READY){ return false; }else{ return true; } }
void WebServer::processConnection(char *buff, int *bufflen) { m_client = m_server.available(); if (m_client) { m_readingContent = false; buff[0] = 0; ConnectionType requestType = INVALID; #if WEBDUINO_SERIAL_DEBUGGING > 1 Serial.println("*** checking request ***"); #endif getRequest(requestType, buff, bufflen); #if WEBDUINO_SERIAL_DEBUGGING > 1 Serial.print("*** requestType = "); Serial.print((int)requestType); Serial.println(", request = \""); Serial.print(buff); Serial.println("\" ***"); #endif processHeaders(); #if WEBDUINO_SERIAL_DEBUGGING > 1 Serial.println("*** headers complete ***"); #endif int urlPrefixLen = strlen(m_urlPrefix); if (strcmp(buff, "/robots.txt") == 0) { noRobots(requestType); } else if (requestType == INVALID || strncmp(buff, m_urlPrefix, urlPrefixLen) != 0 || !dispatchCommand(requestType, buff + urlPrefixLen, (*bufflen) >= 0)) { m_failureCmd(*this, requestType, buff, (*bufflen) >= 0); } #if WEBDUINO_SERIAL_DEBUGGING > 1 Serial.println("*** stopping connection ***"); #endif m_client.stop(); } }
void WebServer::processConnection(char *buff, int *bufflen) { int urlPrefixLen = strlen(m_urlPrefix); m_client = m_server.available(); if (m_client) { m_readingContent = false; buff[0] = 0; ConnectionType requestType = INVALID; getRequest(requestType, buff, bufflen); // don't even look further at invalid requests. // this is done to prevent Webduino from hanging // - when there are illegal requests, // - when someone contacts it through telnet rather than proper HTTP, // - etc. if (requestType != INVALID) { processHeaders(); if (strcmp(buff, "/robots.txt") == 0) { noRobots(requestType); } else if (strcmp(buff, "/favicon.ico") == 0) { favicon(requestType); } } if (requestType == INVALID || strncmp(buff, m_urlPrefix, urlPrefixLen) != 0 || !dispatchCommand(requestType, buff + urlPrefixLen, (*bufflen) >= 0)) { m_failureCmd(*this, requestType, buff, (*bufflen) >= 0); } reset(); if(this->finalCommand != NULL){ this->finalCommand(requestType, this->currentCollection, this->currentModel); this->finalCommand = NULL; } } }
string Socket::receive(int sizeToReceive){ //=0 async read if(closed) { string ret=readBuffer; readBuffer=""; if(ret.size()){ syslog(LOG_INFO,"Received %lu",(long unsigned int)ret.size()); } return ret; } if(header.size()==0) sizeToReceive = JAIL_HEADERS_SIZE_LIMIT; if(sizeToReceive){ syslog(LOG_INFO,"Receiving until %d bytes",sizeToReceive); } //If already read, return data if(sizeToReceive>0 && readBuffer.size()>=sizeToReceive && header.size()!=0){ string ret = readBuffer.substr(0,sizeToReceive); readBuffer.erase(0,sizeToReceive); return ret; } struct pollfd devices[1]; devices[0].fd=socket; devices[0].events=POLLIN; const int MAX=JAIL_NET_BUFFER_SIZE; char buf[MAX]; const int wait=10; // 10 milisec const int bad=POLLERR|POLLNVAL; time_t timeLimit=time(NULL)+JAIL_SOCKET_TIMEOUT; time_t fullTimeLimit=time(NULL)+JAIL_SOCKET_REQUESTTIMEOUT; while(true){ int res=poll(devices,1,wait); if(res==-1) { syslog(LOG_INFO,"poll fail reading %m"); throw HttpException(internalServerErrorCode ,"Error poll reading data"); //Error } time_t currentTime=time(NULL); if(currentTime>timeLimit || currentTime>fullTimeLimit){ if(sizeToReceive==0){ syslog(LOG_DEBUG,"Socket read timeout, closed connection?"); return ""; }else throw HttpException(requestTimeoutCode ,"Socket read timeout"); } if(res==0 && sizeToReceive==0) break; //Nothing to read if(res==0) continue; //Nothing to do syslog(LOG_DEBUG,"poll return: %d",res); if(devices[0].revents & POLLIN){ //Read from net int sizeRead=netRead(buf,MAX); if(sizeRead >0) { string sread(buf,sizeRead); if(sread.size()!=sizeRead){ syslog(LOG_ERR,"read net decode error"); } readBuffer += sread; if(header.size()==0){ size_t pos; if((pos=readBuffer.find("\r\n\r\n")) != string::npos){ header=readBuffer.substr(0,pos+4); syslog(LOG_INFO,"Received header %lu",(long unsigned int)pos+4); processHeaders(header); readBuffer.erase(0,pos+4); return ""; //End of process }else if(readBuffer.size()>JAIL_HEADERS_SIZE_LIMIT){ throw HttpException(requestEntityTooLargeCode,"Http headers too large"); } }else if(sizeToReceive==0 || readBuffer.size()>=sizeToReceive){ //Receive complete break; } timeLimit=currentTime+JAIL_SOCKET_TIMEOUT; //Reset timeout } else if(sizeRead<0){ throw HttpException(badRequestCode ,"Error reading data"); } else { syslog(LOG_INFO,"sizeRead==0"); closed=true; break; } } if(devices[0].revents & POLLHUP){ //socket close closed=true; syslog(LOG_INFO,"POLLHUP"); break; } if(devices[0].revents & bad) { throw HttpException(internalServerErrorCode ,"Error reading data"); } } string ret=readBuffer; readBuffer=""; if(ret.size()){ syslog(LOG_INFO,"Received %lu",(long unsigned int)ret.size()); } return ret; }
int WebSocketHandshake::readServerHandshake(const char* header, size_t len) { m_mode = Incomplete; if (len < sizeof(webSocketServerHandshakeHeader) - 1) { // Just hasn't been received fully yet. return -1; } if (!memcmp(header, webSocketServerHandshakeHeader, sizeof(webSocketServerHandshakeHeader) - 1)) m_mode = Normal; else { const String& code = extractResponseCode(header, len); if (code.isNull()) { m_context->addMessage(ConsoleDestination, JSMessageSource, LogMessageType, ErrorMessageLevel, "Short server handshake: " + String(header, len), 0, clientOrigin()); return -1; } if (code.isEmpty()) { m_mode = Failed; m_context->addMessage(ConsoleDestination, JSMessageSource, LogMessageType, ErrorMessageLevel, "No response code found: " + String(header, len), 0, clientOrigin()); return len; } LOG(Network, "response code: %s", code.utf8().data()); if (code == "401") { m_mode = Failed; m_context->addMessage(ConsoleDestination, JSMessageSource, LogMessageType, ErrorMessageLevel, "Authentication required, but not implemented yet.", 0, clientOrigin()); return len; } else { m_mode = Failed; m_context->addMessage(ConsoleDestination, JSMessageSource, LogMessageType, ErrorMessageLevel, "Unexpected response code:" + code, 0, clientOrigin()); return len; } } const char* p = header + sizeof(webSocketServerHandshakeHeader) - 1; const char* end = header + len + 1; if (m_mode == Normal) { size_t headerSize = end - p; if (headerSize < sizeof(webSocketUpgradeHeader) - 1) { m_mode = Incomplete; return 0; } if (memcmp(p, webSocketUpgradeHeader, sizeof(webSocketUpgradeHeader) - 1)) { m_mode = Failed; m_context->addMessage(ConsoleDestination, JSMessageSource, LogMessageType, ErrorMessageLevel, "Bad Upgrade header: " + String(p, end - p), 0, clientOrigin()); return p - header + sizeof(webSocketUpgradeHeader) - 1; } p += sizeof(webSocketUpgradeHeader) - 1; headerSize = end - p; if (headerSize < sizeof(webSocketConnectionHeader) - 1) { m_mode = Incomplete; return -1; } if (memcmp(p, webSocketConnectionHeader, sizeof(webSocketConnectionHeader) - 1)) { m_mode = Failed; m_context->addMessage(ConsoleDestination, JSMessageSource, LogMessageType, ErrorMessageLevel, "Bad Connection header: " + String(p, end - p), 0, clientOrigin()); return p - header + sizeof(webSocketConnectionHeader) - 1; } p += sizeof(webSocketConnectionHeader) - 1; } if (!strnstr(p, "\r\n\r\n", end - p)) { // Just hasn't been received fully yet. m_mode = Incomplete; return -1; } HTTPHeaderMap headers; p = readHTTPHeaders(p, end, &headers); if (!p) { LOG(Network, "readHTTPHeaders failed"); m_mode = Failed; return len; } if (!processHeaders(headers)) { LOG(Network, "header process failed"); m_mode = Failed; return p - header; } switch (m_mode) { case Normal: checkResponseHeaders(); break; default: m_mode = Failed; break; } return p - header; }
void DeferredData::processDeferredData() { if (m_inProcessDeferredData) return; RecursionGuard guard(m_inProcessDeferredData); // Sending data to webkit causes it to be parsed and javascript executed, // which might cause it to cancel the job or set defersLoading again. So // to be safe, check this after every step. if (m_job.isDeferringLoading() || m_job.isCancelled()) return; if (m_deferredStatusReceived) { m_job.handleNotifyStatusReceived(m_status, m_message); m_deferredStatusReceived = false; if (m_job.isDeferringLoading() || m_job.isCancelled()) return; } if (!processHeaders(m_headerKeys, m_headerValues, &NetworkJob::handleNotifyHeaderReceived) || !processHeaders(m_multipartHeaderKeys, m_multipartheaderValues, &NetworkJob::handleNotifyMultipartHeaderReceived)) return; // Only process 32k of data at a time to avoid blocking the event loop for too long. static const unsigned maxData = 32 * 1024; unsigned totalData = 0; while (!m_dataSegments.isEmpty()) { const Vector<char>& buffer = m_dataSegments.first(); m_job.handleNotifyDataReceived(buffer.data(), buffer.size()); totalData += buffer.size(); if (m_job.isCancelled()) { // Don't bother removing segment; job will be deleted. return; } m_dataSegments.removeFirst(); if (m_job.isDeferringLoading()) { // Stop processing until deferred loading is turned off again. return; } if (totalData >= maxData && !m_dataSegments.isEmpty()) { // Pause for now, and schedule a timer to continue after running the event loop. scheduleProcessDeferredData(); return; } } if (m_totalBytesToBeSent) { m_job.handleNotifyDataSent(m_bytesSent, m_totalBytesToBeSent); m_bytesSent = 0; m_totalBytesToBeSent = 0; } if (m_deferredClose) { m_job.handleNotifyClose(m_deferredCloseStatus); m_deferredClose = false; if (m_job.isDeferringLoading() || m_job.isCancelled()) return; } }