Example #1
0
void thread_client()
{
	try
	{
		printf("[Client] Started\n");
		CClientTCPSocket	sock;

		printf("[Client] Connecting\n");

		sock.connect( "127.0.0.1", 15000 );

		printf("[Client] Connected. Waiting for a message...\n");

//		cout << "pending: " << sock.getReadPendingBytes() << endl;
//		mrpt::system::sleep(4000);
//		cout << "pending: " << sock.getReadPendingBytes() << endl;

		CMessage	msg;
		bool ok = sock.receiveMessage( msg, 2000,2000);

		if (!ok)
		{
			printf("[Client] Error receiving message!!\n");
		}
		else
		{
			printf("[Client] Message received OK!:\n");
			printf("  MSG Type: %i\n", msg.type );
			printf("  MSG Length: %u bytes\n", (unsigned int)msg.content.size() );

			printf("[Client] Parsing image...\n");
			CImage		img;
			msg.deserializeIntoExistingObject( &img );

			printf("[Client] Saving image...\n");
			img.saveToFile("received_frame.jpg");
			printf("[Client] Done!!\n");
		}

		printf("[Client] Finish\n");
	}
	catch(std::exception &e)
	{
		cerr << e.what() << endl;
	}
	catch(...)
	{
		cerr << "[thread_client] Runtime error!" << endl;;
	}
}
Example #2
0
/*---------------------------------------------------------------
							http_get
  ---------------------------------------------------------------*/
ERRORCODE_HTTP  BASE_IMPEXP
mrpt::utils::net::http_get(
	const string	&url,
	vector_byte		&out_content,
	string			&out_errormsg,
	int				port,
	const string	&auth_user,
	const string	&auth_pass,
	int				*out_http_responsecode,
	mrpt::utils::TParameters<string>  *extra_headers,
	mrpt::utils::TParameters<string>  *out_headers,
	int  timeout_ms
	)
{
	// Reset output data:
	out_content.clear();
	if (out_http_responsecode) *out_http_responsecode=0;
	if (out_headers) out_headers->clear();

	// URL must be:
	// http://<SERVER>/<LOCAL_ADDR>

	if (0!=::strncmp(url.c_str(),"http://",7))
	{
		out_errormsg="URL must start with 'http://'";
		return net::erBadURL;
	}

	string server_addr = url.substr(7);
	string get_object = "/";

	// Remove from the first "/" on:
	size_t pos = server_addr.find("/");
	if (pos==0)
	{
		out_errormsg="Server name not found in URL";
		return net::erBadURL;
	}
	if (pos!=string::npos)
	{
		get_object = server_addr.substr(pos);
		server_addr.resize(pos);
	}


	CClientTCPSocket	sock;

	try {
		// Connect:
		sock.connect(server_addr,port, timeout_ms);
	}
	catch (std::exception &e) {
		out_errormsg = e.what();
		return net::erCouldntConnect;
	}

	try {
		// Set the user-defined headers (we may overwrite them if needed)
		TParameters<string>  headers_to_send;
		if (extra_headers)
			headers_to_send=*extra_headers;

		headers_to_send["Connection"]="close"; // Don't keep alive

		if (!headers_to_send.has("User-Agent"))
			headers_to_send["User-Agent"]="MRPT Library";

		// Implement HTTP Basic authentication:
		// See: http://en.wikipedia.org/wiki/Basic_access_authentication
		if (!auth_user.empty())
		{
			string auth_str = auth_user+string(":")+auth_pass;
			vector_byte  v(auth_str.size());
			::memcpy(&v[0],&auth_str [0],auth_str .size());

			string encoded_str;
			mrpt::system::encodeBase64(v,encoded_str);

			headers_to_send["Authorization"]=string("Basic ")+encoded_str;
		}


		// Prepare the request string
		// ---------------------------------
		string req = format(
		  "GET %s HTTP/1.1\r\n"
          "Host: %s\r\n",
		  get_object.c_str(),server_addr.c_str());

		// Other headers:
		for (TParameters<string>::const_iterator i=headers_to_send.begin();i!=headers_to_send.end();++i)
		{
			req+=i->first;
			req+=": ";
			req+=i->second;
			req+="\r\n";
		}

		// End:
		req+="\r\n";

		// Send:
		sock.sendString(req);

		// Read answer:
		vector_byte		buf;
		buf.reserve(1<<14);

		size_t	total_read = 0;
		bool	content_length_read = false;
		bool    all_headers_read = false;
		size_t  content_length = 0;
		size_t  content_offset = 0;
		int		http_code = 0;
		mrpt::utils::TParameters<string>  rx_headers;

		CTicTac  watchdog;
		watchdog.Tic();

		while (!content_length_read || total_read<(content_offset+content_length))
		{
			// Read until "Content-Length: XXX \r\n" is read or the whole message is read,
			//  or an error code is read.
			size_t	to_read_now;

			if (!content_length_read)
			{
				to_read_now = 1500;
			}
			else
			{
				to_read_now	= (content_length+content_offset) -total_read;
			}

			// make room for the data to come:
			buf.resize(total_read+to_read_now+1);

			// Read:
			size_t len = sock.readAsync(&buf[total_read],to_read_now, timeout_ms,100);
			if (!len)
			{
				//
				if (!sock.isConnected())
				{
					if (all_headers_read) // It seems we're done...
						break;
					else
					{
						out_errormsg = "Connection to server was lost";
						return net::erCouldntConnect;
					}
				}

				if ( watchdog.Tac()>1e-3*timeout_ms)
				{
					out_errormsg = "Timeout waiting answer from server";
					return net::erCouldntConnect;
				}
				mrpt::system::sleep(10);
				continue;
			}
			total_read+=len;
			watchdog.Tic();

			buf[total_read]='\0';

			// do we have a \r\n\r\n  ??
			if (!all_headers_read)
			{
				const char *ptr = ::strstr(reinterpret_cast<const char*>(&buf[0]),"\r\n\r\n");
				if (ptr)
				{
					all_headers_read = true;
					const size_t pos_dblret = ((char*)ptr)-(char*)(&buf[0]);

					// Process the headers:
					// ------------------------------
					if (!::strncmp("HTTP/",(const char*)&buf[0], 5))
					{
						http_code = ::atoi( (const char*)&buf[9] );
					}
					else
					{
						// May it be a "SOURCETABLE " answer for NTRIP protocol??
						if (!::strncmp("SOURCETABLE ",(const char*)&buf[0], 12))
						{
							http_code = ::atoi( (const char*)&buf[12] );
						}
						else
						{
							out_errormsg = "Server didn't send an HTTP/1.1 answer.";
							return net::erOtherHTTPError;
						}
					}

					// Check the HTTP code and the content-length:
					content_offset = pos_dblret + 4;

					// Do we have a "Content-Length:"??
					const char *ptr_len = ::strstr(reinterpret_cast<const char*>(&buf[0]),"Content-Length:");
					if (ptr_len)
					{
						content_length = ::atol( ptr_len+15 );
						content_length_read = true;
					}

					// Parse the rest of HTTP headers:
					{
						string aux_all_headers;
						deque<string> lstLines;
						aux_all_headers.resize(content_offset);
						::memcpy( &aux_all_headers[0],&buf[0],content_offset);

						mrpt::system::tokenize(aux_all_headers,"\r\n",lstLines);

						for (deque<string>::const_iterator i=lstLines.begin();i!=lstLines.end();++i)
						{
							const size_t p = i->find(":");
							if (p==string::npos) continue;

							const string key = i->substr(0,p);
							const string val = i->substr(p+2);
							rx_headers[key] = val;
						}
					}

				}
			}
		} // end while


		if (out_http_responsecode) *out_http_responsecode=http_code;
		if (out_headers) *out_headers = rx_headers;

		// Remove the headers from the content:
		buf.erase(buf.begin(),buf.begin()+content_offset);

		// Process: "Transfer-Encoding: chunked"
		if (rx_headers.has("Transfer-Encoding") && rx_headers["Transfer-Encoding"]=="chunked" )
		{
			// See: http://en.wikipedia.org/wiki/Chunked_transfer_encoding

			size_t index = 0;
			while (index<buf.size())
			{
				if (buf[index]=='\r' && buf[index+1]=='\n')
				{
					buf.erase(buf.begin()+index,buf.begin()+index+2);
					continue;
				}

				const char *pCRLF = ::strstr((const char*)&buf[index],"\r\n");
				if (!pCRLF) break;

				const size_t len_substr = ((char*)pCRLF)-(char*)(&buf[index]);

				string  sLen((const char*)&buf[index], len_substr);
				sLen=string("0x")+sLen;

				unsigned int lenChunk;
				int fields = ::sscanf(sLen.c_str(),"%x",&lenChunk);
				if (!fields) break;

				// Remove the len of this chunk header from the data:
				buf.erase(buf.begin()+index,buf.begin()+index+len_substr+2);

				index+=lenChunk;

				if (!lenChunk)
				{
					buf.resize(index);
					break;
				}
			}
		}


		// Set the content output:
		out_content.swap(buf);

		if (http_code==200)
		{
			return net::erOk;
		}
		else
		{
			out_errormsg = format("HTTP error %i",http_code);
			return net::erOtherHTTPError;
		}
	}
	catch (std::exception &e) {
		out_errormsg = e.what();
		return net::erCouldntConnect;
	}

	return net::erOk;
}