XMLRPC on BL5S220

I’m trying to use XMLRPC (with the Rabbit Code Library http://rabbitlib.sourceforge.net/) on a BL5S220.

My problem is it that although the xmlrpc_callback is triggered every time I attempt to access the server (using a Python client on a PC), the code will often not get a positive value from sock_dataready, and the XML content won’t be read.

If I add a bunch of printfs to isolate where things are going wrong, it “fails” far less often. Of course, if I run that code in “run mode”, there are no stdio writes to slow things down and the fail rate increases again.

I’ve tried moving to sock_stringready (since sock_dataready is deprecated), but that doesn’t help. I’ve looked at the various examples which directly use sock_stringready, but nothing jumps out that would make the xmlrpc code fail.

I’m including the xmlrpc.lib callback code for reference. Successful calls trigger tcp_tick 8 times, and receive their first line of XML content after the 2nd tick. Failed calls trigger tcp_tick 12 times, but never receive any XML content.

Any help/insight you can provide would be greatly appreciated.


_xmlrpc_nodebug int xmlrpc_callback( HttpState* state )
{
	auto unsigned char szBuffer[2][512];
	auto int i;
	auto int iBuffer;
	auto char *p;
	auto char szDate[40];
	auto xml_parser_data xmlparserdata;
	auto int iExit;
	auto XmlRpcState xmlrpcstate;
	
	#ifdef DEBUG_XMLRPC
		log( LOG_DEBUG, "xmlrpc_callback" );
	#endif
	
	memset( &xmlrpcstate, 0, sizeof(xmlrpcstate) );
	xmlrpcstate.pBufferCurPos = xmlrpcstate.szBuffer;
	xml_init_parser( &xmlparserdata, xmlrpc_xmlparse_callback, &xmlrpcstate );
	
	// read the xml request
	//  because the xml parser supports a two buffer
	//  system we might as well take advantage of it
	//  so we only read at most 512 bytes at a time
	//  alternating between buffer 1 and 2
	iBuffer = 0;
	iExit = 0;
	i = sock_dataready( &state->s );
	i = sock_read( &state->s, szBuffer[iBuffer], min(sizeof(szBuffer[0]),i) );
	szBuffer[iBuffer][i] = '\0';
	while( iExit == 0 )
	{
		if( xml_append_xml( &xmlparserdata, szBuffer[iBuffer] ) )
		{
			iBuffer++;
			if( iBuffer > 1 ) iBuffer = 0;

			for(;;)
			{
				tcp_tick( &state->s );
				i = sock_dataready( &state->s );
				if( !xml_parse(&xmlparserdata) && i==0 )
				{
					iExit = 1;
					break;
				}
				if( i != 0 )
				{
					i = sock_read( &state->s, szBuffer[iBuffer], min(sizeof(szBuffer[0]),i) );
					szBuffer[iBuffer][i] = '\0';
					break;
				}
			}
		}
		else
		{
			if( !xml_parse( &xmlparserdata ) ) break;
		}
	}
	
	// formulate a response message
	http_date_str( szDate );
	p = szBuffer[0];
	p += sprintf( p, "HTTP/1.0 200 OK
" );
	p += sprintf( p, "Date: %s
", szDate );
	p += sprintf( p, "Content-Type: text/html

" );
	p += sprintf( p, "
" );
	p += sprintf( p, "" );
	p += sprintf( p, "" );
	p += sprintf( p, "" );
	switch( *xmlrpcstate.pSpec->szFuncSig )
	{
	case 'S':
		p += sprintf( p, "<![CDATA[%s]]>", (char*)xmlrpcstate.pRet );
		break;
	case 'I':
		p += sprintf( p, "%d", (int)xmlrpcstate.pRet );
		break;
	}
	p += sprintf( p, "" );
	p += sprintf( p, "" );
	p += sprintf( p, "" );
	
	cgi_sendstring( state, szBuffer[0] );
	return 0;
}

Ends up the server was giving up too quickly and sometimes missed the rest of the message. I’ve solved my problem by waiting for any data to show up before the loop starts.

I’ll probably add a timeout or something to this later, but it works great for now.


i = 0;
while( i == 0 ) {
    tcp_tick( NULL );
    i = sock_dataready( &state->s );
}