Http upload with progress info, in C++ (Poco/Boost) - c++

I'm trying to upload a big file to my http server.
And i need to show a upload progress.
How can i get HOW MANY BYTES are sent during the upload?
Need send events to my GUI.
In poco, i don't know where to put the callback.
_session.sendRequest(_request)
_session.receiveResponse(_response)
Any ideas? or links, Thanks!!

This was 'partially' discussed in 08. Ironically I am looking for exactly the same thing.
http://sourceforge.net/mailarchive/message.php?msg_id=20619477
EDIT: 02/14/12
This is not the best, but it works... probably would best to write 1k blocks at a time.
I'd like to see your suggestions.
std::string szMessage;
.... /* fill your szMessage such as with a Form.write() */ ..
CountingOutputStream _cos( _session.sendRequest(_request) )
std::streamsize len = 0;
string::iterator it;
for ( it=szMessage.begin() ; it < szMessage.end(); it++ ) {
len ++;
_cos.put(*it);
if(len %4096 ==0)
cout << "len: " << len << endl;
}
cout << "Chars printed: " << len << endl;
std::istream& rsout = _session.receiveResponse(_response)
std::ostringstream ostr;
StreamCopier::copyStream(rsout, ostr);
// Retrieve response is not necessary if we have the resp code
std::cout << endl; response.write(cout);
std::cout << ostr.str();
int code = response.getStatus();
if (code != nRespCode) {
stringstream s;
s << "HTTP Error(*): " << code;
throw Poco::IOException(s.str());
}

Related

Trying to generate a timed connection for serial device ttys0 on unix-system

i am trying to generate a class for reading from a specific serial device.
For the start process it is necessary to send a char '1', then i have to wait for a response (254 and 255).
Within a period of 10 milliseconds i must sent the next command to the device, but this time the command length is 5 char.
When the communication hasn´t been send in the correct time, the device will run into a timeout and is sending me 255,255,255,2,4.
So i need different sizes of reading and the most importing thing for me is a timeout for the communication, cause otherwise the system will stop working by missing some values.
Therefore i have tried to generate a class using boost::asio::async_read.
It is working in the correct way, i can define the timeout,also the size of bytes to be read. When the device isn´t sending the correct size, the routine is going to be left.
But only the first time, when i try it a second time, the device isn´t sending me something. I have tried to use .open again, but it isn´t solving the issue. Also deactivating the close-function isn´t solving the issue, then the routine is running into an error.
Can someone give me a small tip for my issue. Maybe i am to blind to see my problem.... Bernd
ConnectionWithTimeout::ConnectionWithTimeout(int timeout_)
: timer_(io_service_, boost::posix_time::milliseconds(timeout_))
, serial_port_(io_service_) {
}
void ConnectionWithTimeout::ReadNumberOfChars(int numberOfCharactersToRead_)
{
buffer_.resize(numberOfCharactersToRead_);
for (int i = 0; i < numberOfCharactersToRead_; ++i) {
std::cout << "Clear Buffer[" << i << "]" << std::endl;
buffer_[i] = 0;
}
timer_.async_wait(boost::bind(&::ConnectionWithTimeout::Stop, this));
//async read from serial port
boost::asio::async_read(serial_port_, boost::asio::buffer(buffer_),
boost::bind(&ConnectionWithTimeout::ReadHandle, this,
boost::asio::placeholders::error));
io_service_.run();
}
void ConnectionWithTimeout::Stop() {
std::cout << "Connection is being closed." << std::endl;
serial_port_.close();
std::cout << "Connection has been closed." << std::endl;
}
void ConnectionWithTimeout::ReadHandle(const boost::system::error_code& ec) {
if (ec) {
std::cout << "The amount of data is to low: " << ec << std::endl;
for (std::vector<char>::iterator it = buffer_.begin();
it != buffer_.end(); ++it)
{
std::cout << int(*it) << std::endl;
}
}
else {
std::cout << "The amount of data is correct: " << ec << std::endl;
for (std::vector<char>::iterator it = buffer_.begin(); it !=
buffer_.end(); ++it)
{
std::cout << int(*it) << std::endl;
}
}
}

How to parse json data from websocket_client using cpprestsdk

I'm connecting to a WebSocket whom always replies in JSON. I see there is an extract_string method for websocket_incoming_message however after trying numerous things with json:value it seems as though you can only construct JSON arrays on-the-fly by inserting key-value pairs one-by-one. Am I missing something here or is there a way to take the output from websocket_incoming_message and directly convert it into a json:value array?
websocket_client client;
//start socket connection to server
try {
std::cout << "s
----------
client.connect(U("wss://XZXXXZZy.com/ws?account_id=4de3f308f2f8d3247As70228f94e0d2aAea&ws_key=reception")).wait();
}
catch (const std::exception&e)
{
std::cout << e.what() << std::endl;
}
//send messages to the server
//websocket_outgoing_message msg;
//msg.set_pong_message();
//std::cout << "\n...........2nd.........;";
//std::string data = "hii";
//client.send(msg).then([]() {
//
//
//
//
// /* Successfully sent the message. */ });
//std::cout << " Successfully sent the message.";
//std::cout << "\n...........3rd.........;";
//receive messages from the server
client.receive().then([](websocket_incoming_message msg) {
std::cout << "receiving data from socket";
return msg.extract_string();
}).then([](std::string body) {
//FETCHING THE DATA FROM BODY. "TEXT/JSON"
std::cout << "displaying the data";
std::cout << body << std::endl;
const json::value& v1 = body.substr;
utility::string_t jsonval = v1.serialize();
auto array = v1.at(U("rows")).as_array();
for (int i = 0; i<array.size(); ++i)
{
auto id = array[i].at(U("id")).as_string();
std::wcout << "\n" << id;
auto key = array[i].at(U("key")).as_string();
std::wcout << "\n" << key;
auto array2 = array[i].at(U("value")).as_array();
std::wcout << array2[0];
std::wcout << array2[1];
}
}
);
//close the connection
client.close().then([]() {
std::cout << "successfully close socket connction";
/* Successfully closed the connection. */
});
I have json response in my string body.but i dont know how to parse json data from websocket responses event. i want to display contacts from api responses.please help me..
MY JSON RESPONSES
--------------------------------------
.{"action":"refresh_dashboard","data":{"users_list":[{"user_id":"901e6076ff351cfc2195fb86f8438a26","extensions":["1002"],"name":"Karthik M"},{"user_id":"cc3f94ecc14ee9c55670dcde9adc1887","extensions":["1006"],"name":"Rounak S Kiran"},{"user_id":"6c29ebdb34e1761fdf9423c573087979","extensions":["1003"],"name":"Amar Nath"},{"user_id":"74d5b5a9aca1faa4c2f217ce87b621d8","extensions":["1008"],"name":"Robin Raju"},{"user_id":"a7ad7e73bf93ea83c8efdc1723cba198","extensions":["1007"],"name":"Arshad Arif"},{"user_id":"b55146df593ec8d09e5fe12a8a4c1108","extensions":["1001"],"name":"Rahib Rasheed"},{"user_id":"3258f7ae4ae1db60435cbcf583f64a89","extensions":["1009"],"name":"Test User"},{"user_id":"90bc84e5e8a3427fe35e99bd4386de95","extensions":["1010"],"name":"Prince T"},{"user_id":"b501ef5b270a196afc0eed557ca74237","extensions":["1005","+17325951060"],"name":"Jineed AJ"},{"user_id":"1422af351e06adeab2de92f5a633a444","extensions":["1004"],"name":"Ashok PA"}],"busy_users":[],"reg_users":[{"user_id":"cc3f94ecc14ee9c55670dcde9adc1887","status":"registered"},{"user_id":"901e6076ff351cfc2195fb86f8438a26","status":"registered"},{"user_id":"1422af351e06adeab2de92f5a633a444","status":"registered"},{"user_id":"3258f7ae4ae1db60435cbcf583f64a89","status":"registered"},{"user_id":"b55146df593ec8d09e5fe12a8a4c1108","status":"registered"},{"user_id":"6c29ebdb34e1761fdf9423c573087979","status":"registered"}],"contacts":[{"owner_id":"cc3f94ecc14ee9c55670dcde9adc1887","status":"ready"},{"owner_id":"901e6076ff351cfc2195fb86f8438a26","status":"ready"},{"owner_id":"1422af351e06adeab2de92f5a633a444","status":"ready"},{"owner_id":"3258f7ae4ae1db60435cbcf583f64a89","status":"ready"},{"owner_id":"b55146df593ec8d09e5fe12a8a4c1108","status":"ready"},{"owner_id":"6c29ebdb34e1761fdf9423c573087979","status":"ready"}]}}
I got the complete solution .please try to use boost pacakges from nuget. The documentation will help you to parse the json data from string. I think jsoncpp is not an updated packages available in the nuget.so please try boost packages available in the nuget.
MYJSON STRING
{"action":"refresh_dashboard","data":{"users_list":[{"user_id":"901e6076ff351cfc2195fb86f8438a26","extensions":["1002"],"name":"Karthik M"},{"user_id":"7d617ef5b2390d081d901b0d5cd108eb","extensions":["1015"],"name":"Synway User2"},{"user_id":"c8f667f7d663e81f6e7fa34b9296f067","extensions":["1012"],"name":"Rahib Video"},{"user_id":"cc3f94ecc14ee9c55670dcde9adc1887","extensions":["1006"],"name":"Rounak S Kiran"},{"user_id":"6c29ebdb34e1761fdf9423c573087979","extensions":["1003"],"name":"Amar Nath"},{"user_id":"8e15c2d95d4325cb07f0750846966be8","extensions":["1011"],"name":"TLS User"},{"user_id":"2fc4142bdacf83c1957bda0ad9d50e3d","extensions":["1014"],"name":"Synway User1"},{"user_id":"74d5b5a9aca1faa4c2f217ce87b621d8","extensions":["1008"],"name":"Robin Raju"},{"user_id":"a7ad7e73bf93ea83c8efdc1723cba198","extensions":["1007"],"name":"Arshad Arif"},{"user_id":"b55146df593ec8d09e5fe12a8a4c1108","extensions":["1001"],"name":"Rahib Rasheed"},{"user_id":"391391de005a8f5403c7b5591f462ea1","extensions":["1013"],"name":"Sangeeth J"},{"user_id":"3258f7ae4ae1db60435cbcf583f64a89","extensions":["1009"],"name":"Aby TL"},{"user_id":"90bc84e5e8a3427fe35e99bd4386de95","extensions":["1010"],"name":"Prince T"},{"user_id":"b501ef5b270a196afc0eed557ca74237","extensions":["1005"],"name":"Jineed AJ"},{"user_id":"1422af351e06adeab2de92f5a633a444","extensions":["1004"],"name":"Ashok PA"}],"busy_users":[],"reg_users":[{"user_id":"901e6076ff351cfc2195fb86f8438a26","status":"registered"},{"user_id":"6c29ebdb34e1761fdf9423c573087979","status":"registered"}],"contacts":[{"owner_id":"901e6076ff351cfc2195fb86f8438a26","status":"ready"},{"owner_id":"6c29ebdb34e1761fdf9423c573087979","status":"ready"}]}}
CODES
client.receive().then([](websocket_incoming_message msg) {
std::cout << "receiving data from socket";
// msg.message_type();
return msg.extract_string();
//1..i have one string
//cout<<"\n///////////test"<< msg.extract_string().get().c_str();
// // 2.convert to json array
//json::value::parse( ::to_string_t(msg.extract_string().get()))
//
}).then([](std::string body) {
//std::cout << "displaying the data";
std::cout << body << std::endl;
std::string ss = body;
ptree pt;
std::istringstream is(ss);
read_json(is, pt);
std::cout <<"\n 1st"<< "action: " << pt.get<std::string>("action") << "\n";
std::cout <<"\n 2nd"<< "data: " << pt.get<std::string>("data") << "\n";
std::cout << "--------------------------------------------------------------";
for (auto& e : pt.get_child("data.users_list")) {
std::cout << "\n" << "users id " << e.second.get<std::string>("user_id") << "\n";
}
});
useful resources
Parse JSON array as std::string with Boost ptree
C++ boost parse dynamically generated json string (not a file)

Clearing the cout buffer (c++)

Hello I'm writing a short program to implement a shell and I'm running into an unusual problem. For some reason I can't clear to the std::cout buffer. The program wont print out messages. I understand a simple solution is to switch to std::cerr, but is there a way to get messages to print with cout?
Things I've tryed:
std::cout.flush()
Inserting std::endl after anything is written to standard out.
Inserting an std::flush into the output stream
std::cout.setf(std::ios::unitbuf); which was something I found that should unbuffer output.
Any help is much appreciated here is my code:
int main()
{
//Tryed this to unbuffer cout, no luck.
std::cout.setf(std::ios::unitbuf);
std::string input;
//Print out shell prompt and read in input from keyboard.
std::cout << "myshell> ";
std::getline(std::cin, input);
//**********************************************************************
//Step 1) Read in string and parse into tokens.
//**********************************************************************
char * buf = new char[input.length() + 1];
strcpy(buf, input.c_str());
int index = 0;
char * command[256];
command[index] = std::strtok(buf, " "); //Get first token.
std::cout << command[index] << std::endl;
while (command[index] != NULL)
{
++index;
command[index] = std::strtok(NULL," "); //Get remaining tokens.
std::cout << command[index] << std::endl;
}
std::cout.flush(); //No luck here either
//HERE IS WHERE MY PROBLEM IS.
std::cout << index << " items were added to the command array" << std::endl;
delete[] buf;
return 0;
}
The problem is that you're sending NULL to cout on the last iteration of the while loop, which leads to UB, and in your case is jamming cout. Check for NULL before you send anything to cout and you're fine:
if (command[index] != NULL) {
std::cout << command[index] << std::endl;
}
If you ever need to know what happened to your streams, remember that they can carry status information (the iostate, which I recommend you read about). The following code could have helped track your error:
try {
std::cout.exceptions(std::cout.failbit);
} catch(const std::ios_base::failure& e) {
std::cerr << "stream error: " << e.what() << std::endl;
std::cout.clear();
}
// continue working with cout, because std::cout.clear() removed
// failbit
Or, even simpler:
if(not std::cout) {
// address your error (if it is recoverable)
}
This is how your code would have looked like:
#include <cstring>
#include <string>
#include <iostream>
int main()
{
//Tryed this to unbuffer cout, no luck.
std::cout.setf(std::ios::unitbuf);
std::string input;
//Print out shell prompt and read in input from keyboard.
std::cout << "myshell> ";
std::getline(std::cin, input);
//**********************************************************************
//Step 1) Read in string and parse into tokens.
//**********************************************************************
char * buf = new char[input.length() + 1];
strcpy(buf, input.c_str());
int index = 0;
char * command[256];
command[index] = std::strtok(buf, " "); //Get first token.
std::cout << command[index] << std::endl;
while (command[index] != NULL)
{
++index;
command[index] = std::strtok(NULL," "); //Get remaining tokens.
std::cout << command[index] << std::endl;
}
// I added from here...
if(not std::cout) {
std::cerr << "cout is messed up... fixing it..." << std::endl;
std::cout.clear();
}
// ... to here.
std::cout.flush(); //No luck here either
//HERE IS WHERE MY PROBLEM IS.
std::cout << index << " items were added to the command array" << std::endl;
delete[] buf;
return 0;
}
Result:
$ ./a.out
myshell> 1 2 3
1
2
3
cout is messed up... fixing it...
3 items were added to the command array

C++ getting a seg fault before even entering a function

I have a problem where I try to compress a file's data. Everything works up to the compression call, but it isn't the compression call itself, as the segfault is thrown before it. Showing my code will make it much clearer:
std::cout << "FILENAME: ";
std::cin >> filename;
if(!fileExists(filename))
{
std::cout << "ERR: FILE NOT FOUND." << std::endl;
continue;
}
std::cout << "Compressing file data...";
writeFile(filename, zlib_compress(readFile(filename)));
std::cout << " Done." << std::endl;
At the function zlib_compress...
std::string zlib_compress(const std::string& str)
{
std::cout << "DEBUG" << std::endl;
z_stream zs; // z_stream is zlib's control structure
memset(&zs, 0, sizeof(zs));
if (deflateInit(&zs, 9) != Z_OK)
std::cout << "deflateInit failed while compressing." << std::endl;
zs.next_in = (Bytef*)str.data();
zs.avail_in = str.size(); // set the z_stream's input
int ret;
char outbuffer[1073741824];
std::string outstring;
// retrieve the compressed bytes blockwise
do
{
zs.next_out = reinterpret_cast<Bytef*>(outbuffer);
zs.avail_out = sizeof(outbuffer);
ret = deflate(&zs, Z_FINISH);
if (outstring.size() < zs.total_out)
{
// append the block to the output string
outstring.append(outbuffer, zs.total_out - outstring.size());
}
} while(ret == Z_OK);
deflateEnd(&zs);
if(ret != Z_STREAM_END) // an error occurred that was not EOF
{
std::ostringstream oss;
oss << "Exception during zlib compression: (" << ret << ") " << zs.msg;
std::cout << oss.str();
}
return outstring;
}
I know, I know, that function needs work, I just C&P'd from somewhere to try it out.
But the thing is this:
std::cout << "DEBUG" << std::endl; is never called. The compiler says that the seg fault is coming from here:
std::string zlib_compress(const std::string& str)
> {
But why...? It was working earlier. I just don't know what went wrong!
Edit: Debugger output.
#0 00000000 0x00402cbb in __chkstk_ms() (??:??)
#1 004013BE zlib_compress(str=...) (C:\Users\***\Documents\Work\Programming\Compressor\z.cpp:5)
#2 00401DDA _fu15___ZSt4cout() (C:\Users\***\Documents\Work\Programming\Compressor\main.cpp:80)
char outbuffer[1073741824];
That's too large to put on the stack
You are taking a constant reference to a string as a parameter in your zlib_compress - you need to make sure that memory is available (whatever is returned from your readfile) in your zlib_compress. It would be good if you can share the prototype of your readFile function too.

SFML TCP packets being changed

After failing to get any help in the SFML forums, I've decided to see if anyone here can be of any help. I have an application which updates itself through a TCP connection to a server application. This works perfectly fine, except for one specific packet transmission, in which the packet is somehow changed. The server sends a packet containing the number 1:
pack << sf::Uint8(1);
ClientSocket.Send(pack);
(Where pack is of type sf::Packet and ClientSocket is of type sf::SocketTCP)
Stepping through with my debugger does in fact confirm that these lines are executed, and that the next Receive call in my client is the next few lines:
sock.Receive(pack);
sf::Uint8 conf;
pack >> conf;
(Where pack is once again an sf::Packet, and sock is a SocketTCP)
However, somehow in my client, conf is showing up as having a value of zero (my debugger confirms this) and it acts as so (the next line switches depending on the value). I am running both applications on the same machine, and they are both reading each other as "127.0.0.1", so the packets (if I understand correctly) aren't going through my router, or really ever leaving my machine. Any ideas on why my packets are being corrupted?
For the record, in case it's any help, I'm using SFML 1.6 and my application in being run on a Debian Squeeze Linux machine.
EDIT: Per request, here is some more code from my application.
First, the portion of my client specifically relating to this updater:
cout << "Connecting to update server." << endl;
sf::IpAddress server = sf::IpAddress::LocalHost;
sf::TcpSocket sock;
if (sock.connect(server, PORT, sf::seconds(20.0f)) != sf::Socket::Done)
return false;
cout << "Connected. Searching for updates for updater." << endl;
sf::Packet pack;
std::string lastUpdate = getLastUpdate();
#ifdef __WXGTK__
pack << "uupdate" << lastUpdate << sf::Uint8(1);
#elif defined(__WXMSW__)
pack << "uupdate" << lastUpdate << sf::Uint8(2);
#elif defined(__WXOSX__)
pack << "uupdate" << lastUpdate << sf::Uint8(3);
#endif
sock.send(pack);
pack.clear();
sock.receive(pack); //THIS IS THE PART WHERE IT BREAKS
sf::Int32 conf;
pack >> conf;
if (conf == 1) { //There is an update!
cout << "Update found!" << endl;
pack << "begin" << sf::Uint32(512);
sock.send(pack);
pack.clear();
sock.receive(pack);
pack >> conf;
if (conf == 0) { //No errors
wxFileOutputStream* out = new wxFileOutputStream(wxString(UPDATER, StrConv).append(".temp"));
char* data = new char[512];
while (data != chara("done") && data != chara("error")) {
sock.receive(pack);
sf::Int32 size;
pack >> size;
data = const_cast<char*>((const char*)pack.getData());
out->Write(data, size);
}
out->Close();
if (data == chara("done"))
wxCopyFile(wxString(UPDATER, StrConv).append(".temp"), wxString(UPDATER, StrConv));
wxRemoveFile(wxString(UPDATER, StrConv).append(".temp"));
}
}
cout << "Updater is up-to-date. Executing updater." << endl;
sock.disconnect();
bool success;
if (wxTheApp->argc == 1)
success = wxExecute(wxT(UPDATER));
else
success = wxExecute(wxString(UPDATER, StrConv).append(wxTheApp->argv[1]));
return success;
And then the portion of the server relating to these updates:
//ClientSocket has already been initalised by way of a TcpListener
cout << "Checking for updater patches for client at " << ClientAddress.toString() << endl;
std::string lastUpdate;
pack >> lastUpdate;
sf::Uint8 os;
pack >> os;
//Check last time updater was changed
struct tm* clock;
struct stat attribs;
if (os == 1)
stat("Linux/Updater", &attribs);
else if (os == 2)
stat("Windows/Updater.exe", &attribs);
else if (os == 3)
stat("Mac/Updater", &attribs);
clock = gmtime(&(attribs.st_mtime));
time_t lastWrite = mktime(clock);
time_t clientUpdate = stringToNumber<time_t>(lastUpdate.c_str());
if (lastWrite > clientUpdate) {
cout << "Found updater patches for client at " << ClientAddress.toString() << endl;
pack << sf::Int32(1);
ClientSocket->send(pack); //THIS IS THE PART WHERE IT BREAKS
pack.clear();
ClientSocket->receive(pack);
std::string mes;
pack >> mes;
if (mes != "begin") {
cerr << "Client at " << ClientAddress.toString() << " sent unrecognised message: " << mes << ". Ending conversation." << endl;
ClientSocket->disconnect();
return false;
}
sf::Uint32 size;
pack >> size;
cout << "Beginning to send updater patch to " << ClientAddress.toString() << endl;
ifstream in;
if (os == 1)
in.open(chara("Linux/Updater"), ios_base::in | ios_base::binary);
else if (os == 2)
in.open(chara("Windows/Updater.exe"), ios_base::in | ios_base::binary);
else if (os == 3)
in.open(chara("Mac/Updater"), ios_base::in | ios_base::binary);
if (in.fail()) {
pack << sf::Uint8(1);
ClientSocket->send(pack);
cerr << "Failed to open updater at request of " << ClientAddress.toString() << ". Closing connection." << endl;
ClientSocket->disconnect();
return false;
}
pack << sf::Uint8(0);
ClientSocket->send(pack);
pack.clear();
//Get length of file
in.seekg(0, ios::end);
int length = in.tellg();
in.seekg(0, ios::end);
char* buf = new char[size];
for (unsigned int i = 0; i < length / size; i++) { //Read and send every `size`-sized block we can
in.read(buf, size);
pack << sf::Int32(size) << buf;
ClientSocket->send(pack);
}
in.read(buf, length % size);
pack << sf::Int32(length % size) << buf;
ClientSocket->send(pack);
pack.clear();
pack << "done";
ClientSocket->send(pack);
pack.clear();
} else {
pack << sf::Int8(0);
ClientSocket->send(pack);
}
EDIT: I know it's been almost a month since there have been any posts on here, but I'm still having issues with this. I'm at wit's end on how to solve this.
This is not really an answer but I can't add a comment on the question so...
SFML 1.6 is not maintained and if there is an issue with SFML itself it might already be solved in version 2.0. You can download the RC here.
So, turns out the problem was rather simple. You know how I added lots of pack.clear() lines in? Turns out I forgot to add one between receiving the original data and sending the original data on the server. So my packet still had data left over from the first call to sock.receive(pack) (which was a few lines above the start of the code from the server posted above). It took me this long to see that. Put in a call to pack.clear() and the problem went away.