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;; } }
/*--------------------------------------------------------------- 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; }