Пример #1
0
static void DoHTTP( uint8_t timed )
{
	switch( curhttp->state )
	{
	case HTTP_STATE_NONE: //do nothing if no state.
		break;
	case HTTP_STATE_DATA_XFER:
		if( TCPCanSend( curhttp->socket, 1024 ) ) //TCPDoneSend
		{
			if( curhttp->is_dynamic )
			{
				HTTPCustomCallback( );
			}
			else
			{
				HTTPHandleInternalCallback( );
			}
		}
		break;
	case HTTP_WAIT_CLOSE:
		if( TCPDoneSend( curhttp->socket ) )
		{
			if( curhttp->keep_alive )
			{
				curhttp->state = HTTP_STATE_WAIT_METHOD;
			}
			else
			{
				HTTPClose( );
			}
		}
		break;
	case HTTP_STATE_DATA_WEBSOCKET:
		if( TCPCanSend( curhttp->socket, 1024 ) ) //TCPDoneSend
		{
			WebSocketTickInternal();
		}
		break;
	default:
		if( timed )
		{
			if( curhttp->timeout++ > HTTP_SERVER_TIMEOUT )
			{
				HTTPClose( );
			}
		}
	}
}
Пример #2
0
void HTTPCustomCallback( )
{
	uint16_t i, bytestoread;
	struct HTTPConnection * h = curhttp;

	if( h->isdone )
	{
		HTTPClose( h->socket );
		return;
	}
	if( h->isfirst )
	{
		TCPs[h->socket].sendtype = ACKBIT | PSHBIT;
		StartTCPWrite( h->socket );
		//TODO: Content Length?  MIME-Type?
		PushStr( "HTTP/1.1 200 Ok\r\nConnection: close\r\n\r\n" );

		if( strncmp( h->pathbuffer, "/d/r1?", 6 ) == 0 )
		{
			char outb[3] = {0, 0, 0};
			char * bp = h->pathbuffer + 6;
			unsigned char address = 0;
			address += hex2val( *(bp++) )<<4;
			address += hex2val( *(bp++) );

			unsigned char * cc = (unsigned char*)address;

			int8tohex( *cc, outb );
			PushStr( outb );
		}
		else if( strncmp( h->pathbuffer, "/d/w1?", 6 ) == 0 )
		{
			char * bp = h->pathbuffer + 6;
			unsigned char address = 0;
			address += hex2val( *(bp++) )<<4;
			address += hex2val( *(bp++) );

			unsigned char value = 0;
			value += hex2val( *(bp++) )<<4;
			value += hex2val( *(bp++) );

			unsigned char * cc = (unsigned char*)address;
			*cc = value;
		}
		else if( strncmp( h->pathbuffer, "/d/r2?", 6 ) == 0 )
		{
			char outb[3] = {0, 0, 0};
			char * bp = h->pathbuffer + 6;
			unsigned char address = 0;
			address += hex2val( *(bp++) )<<4;
			address += hex2val( *(bp++) );

			unsigned short * cc = (unsigned char*)address;
			unsigned short vo = *cc;
			int8tohex( vo>>8, outb );
			PushStr( outb );
			int8tohex( vo&0xff, outb );
			PushStr( outb );
		}
Пример #3
0
void TCPConnectionClosing( uint8_t conn )
{
	if( conn >= HTTP_CONNECTIONS )
	{
		sendstr( "LOSC\n" );
		RemovePlayer( conn - HTTP_CONNECTIONS - 1 );
	}
#ifndef NO_HTTP
	else
	{
		curhttp = &HTTPConnections[conn-1];
		HTTPClose(  );
	}
#endif
}
Пример #4
0
void ICACHE_FLASH_ATTR HTTPGotData( )
{
	uint8 c;
	curhttp->timeout = 0;
	while( curlen-- )
	{
		c = HTTPPOP;
	//	sendhex2( h->state ); sendchr( ' ' );

		switch( curhttp->state )
		{
		case HTTP_STATE_WAIT_METHOD:
			if( c == ' ' )
			{
				curhttp->state = HTTP_STATE_WAIT_PATH;
				curhttp->state_deets = 0;
			}
			break;
		case HTTP_STATE_WAIT_PATH:
			curhttp->pathbuffer[curhttp->state_deets++] = c;
			if( curhttp->state_deets == MAX_PATHLEN )
			{
				curhttp->state_deets--;
			}
			
			if( c == ' ' )
			{
				//Tricky: If we're a websocket, we need the whole header.
				curhttp->pathbuffer[curhttp->state_deets-1] = 0;
				curhttp->state_deets = 0;

				if( strncmp( (const char*)curhttp->pathbuffer, "/d/ws", 5 ) == 0 )
				{
					curhttp->state = HTTP_STATE_DATA_WEBSOCKET;
					curhttp->state_deets = 0;
				}
				else
				{
					curhttp->state = HTTP_STATE_WAIT_PROTO; 
				}
			}
			break;
		case HTTP_STATE_WAIT_PROTO:
			if( c == '\n' )
			{
				curhttp->state = HTTP_STATE_WAIT_FLAG;
			}
			break;
		case HTTP_STATE_WAIT_FLAG:
			if( c == '\n' )
			{
				curhttp->state = HTTP_STATE_DATA_XFER;
				InternalStartHTTP( );
			}
			else if( c != '\r' )
			{
				curhttp->state = HTTP_STATE_WAIT_INFLAG;
			}
			break;
		case HTTP_STATE_WAIT_INFLAG:
			if( c == '\n' )
			{
				curhttp->state = HTTP_STATE_WAIT_FLAG;
				curhttp->state_deets = 0;
			}
			break;
		case HTTP_STATE_DATA_XFER:
			//Ignore any further data?
			curlen = 0;
			break;
		case HTTP_STATE_DATA_WEBSOCKET:
			WebSocketGotData( c );
			break;
		case HTTP_WAIT_CLOSE:
			if( curhttp->keep_alive )
			{
				curhttp->state = HTTP_STATE_WAIT_METHOD;
			}
			else
			{
				HTTPClose( );
			}
			break;
		default:
			break;
		};
	}

}
Пример #5
0
void ICACHE_FLASH_ATTR HTTPHandleInternalCallback( )
{
	uint16_t i, bytestoread;

	if( curhttp->isdone )
	{
		HTTPClose( );
		return;
	}
	if( curhttp->is404 )
	{
		START_PACK
		PushString("HTTP/1.1 404 Not Found\r\nConnection: close\r\n\r\nFile not found.");
		EndTCPWrite( curhttp->socket );
		curhttp->isdone = 1;
		return;
	}
	if( curhttp->isfirst )
	{
		char stto[10];
		uint8_t slen = os_strlen( curhttp->pathbuffer );
		const char * k;

		START_PACK;
		//TODO: Content Length?  MIME-Type?
		PushString("HTTP/1.1 200 Ok\r\n");

		if( curhttp->bytesleft < 0xfffffffe )
		{
			PushString("Connection: "ISKEEPALIVE"\r\nContent-Length: ");
			Uint32To10Str( stto, curhttp->bytesleft );
			PushBlob( stto, os_strlen( stto ) );
			curhttp->keep_alive = 1;
		}
		else
		{
			PushString("Connection: close\r\n");
			curhttp->keep_alive = 0;
		}

		PushString( "\r\nContent-Type: " );
		//Content-Type?
		while( slen && ( curhttp->pathbuffer[--slen] != '.' ) );
		k = &curhttp->pathbuffer[slen+1];
		if( strcmp( k, "mp3" ) == 0 )
		{
			PushString( "audio/mpeg3" );
		}
		else if( strcmp( k, "gz" ) == 0 )
		{
			PushString( "text/plain\r\nContent-Encoding: gzip\r\nCache-Control: public, max-age=3600" );			
		}
		else if( curhttp->bytesleft == 0xfffffffe )
		{
			PushString( "text/plain" );
		}
		else
		{
			PushString( "text/html" );
		}

		PushString( "\r\n\r\n" );
		EndTCPWrite( curhttp->socket );
		curhttp->isfirst = 0;

		return;
	}

	START_PACK

	for( i = 0; i < 4 && curhttp->bytesleft; i++ )
	{
		int bpt = curhttp->bytesleft;
		if( bpt > MFS_SECTOR ) bpt = MFS_SECTOR;
		curhttp->bytesleft = MFSReadSector( generic_ptr, &curhttp->data.filedescriptor );
		generic_ptr += bpt;
	}

	EndTCPWrite( curhttp->socket );

	if( !curhttp->bytesleft )
		curhttp->isdone = 1;
}
Пример #6
0
void TCPConnectionClosing( uint8_t conn )
{
//	sendstr( "Lostconn\n" );
	HTTPClose( conn );
}
Пример #7
0
int main(int argc, char** argv)
{
	if (argc < 2)
		return usage(argc, argv);

	parent = pthread_self();
	sigset_t original, masking;
	sigemptyset(&original);
	sigemptyset(&masking);
	sigaddset(&masking, SIGUSR1);
	pthread_sigmask(SIG_SETMASK, &masking, &original);

	int wakeupThreads = 0;
	try
	{
		wakeupThreads = lexicalCast<int>(argv[argc-1]);
		if (wakeupThreads < 1)
			return usage(argc, argv);

		std::cout << "wakeup threads of " << wakeupThreads << std::endl;
	}
	catch (std::exception& e)
	{
		std::cerr << e.what() << std::endl;
		return usage(argc, argv);
	}

	void* handle = WWWInit();
	std::vector<Item> items = loadItems();
	resetItems(items);
	void* filterManagerContext = FilterManagerCreate(NULL);

	std::map<void*, void*> contextMap;
	

	// create threads.
	for (int count = 0; count != wakeupThreads; ++count)
	{
		std::vector<Item>::iterator itor = find_uncheck_item(items);
		if (itor == items.end())
			break;

		itor->check_flg = true;
		void* thread = ThreadCreate();
		void* httpContext = HTTPCreateContext(itor->url_check.c_str(),
											  NULL, NULL, 20);
		contextMap[thread] = httpContext;
		std::cout << "thread: " << thread <<
			"   context: " << httpContext << std::endl;
		ThreadStart(thread, httpContext, handler);
	}

	try
	{
		std::vector<Item>::iterator itor;
		while ((itor = find_uncheck_item(items)) != items.end())
		{
			itor->check_flg = true;
			
			int signalNum = 0;
			sigwait(&masking, &signalNum);
			if (signalNum == SIGUSR1)
			{
				// signal一回で複数の待ちハンドラを処理した方が良さそう
				ScopedLock<Mutex> lock(syncObject);
				assert (idleThreads.size() > 0);
				void* thread = idleThreads.back();
				idleThreads.pop_back();
				ThreadJoin(thread);

				void* httpContext = contextMap[thread];
				assert(httpContext != NULL);
				contextMap[thread] = NULL;

				{
					char url[2048];
					url[HTTPGetURL(httpContext, url, sizeof(url))] = 0;
					std::vector<Item>::iterator item_itor =
						find_item_from_url(items, url);

					if (item_itor == items.end())
						throw std::runtime_error((std::string("unfind URL: ") +
												  url).c_str());

					char date[256];
					date[HTTPGetLastModified(httpContext,
											 date, sizeof(date))] = 0;
					item_itor->last_updated = date;

					item_itor->crc32 = HTTPGetFilteredCRC32(httpContext,
													   filterManagerContext);
				
					item_itor->content_length =
						HTTPGetContentsLength(httpContext);

					HTTPClose(httpContext);
				}
				HTTPCreateContext(itor->url_check.c_str(),
								  NULL, NULL, 20);
				contextMap[thread] = httpContext;
				std::cout << "thread: " << thread <<
					"   context: " << httpContext << std::endl;
				ThreadStart(thread, httpContext, handler);
			}
		}

		// 稼働中のスレッドがwakeupThreads個存在する
		for (int count = 0; count != wakeupThreads; ++count)
		{
			int signalNum = 0;
			// signal一回で複数の待ちハンドラを処理した方が良さそう
			sigwait(&masking, &signalNum);
			ScopedLock<Mutex> lock(syncObject);
			ThreadClose(idleThreads.back());
			idleThreads.pop_back();
		}
	}
	catch (std::exception& e)
	{
		std::cerr << "raise exception: " << e.what() << std::endl;
	}
	catch (...)
	{
		std::cerr << "unknown exception raised." << std::endl;
	}

	saveItems(items);
	FilterManagerTerminate(filterManagerContext);
	WWWTerminate(handle);
	pthread_sigmask(SIG_SETMASK, &original, NULL);

	return 0;
}