I'm playing a little with ifstream on macOS with clang.
I'm trying to read the whole file using the read method:
ifstream is(filename);
is.exceptions(ifstream::failbit | ifstream::badbit);
// This set up a buffer with a size of 2048 bytes.
void *buff = XML_GetBuffer(parser, 2048);
do {
is.read(reinterpret_cast<char*>(buff), 2048);
auto charBuff = reinterpret_cast<char*>(buff);
std::cout << charBuff << std::endl;
} while (!is.eof());
is.close();
By processing a long file, an exception is thrown:
ios_base::clear: unspecified iostream_category error
I tried to get more information with strerror(errno) but I only get :
Err:Undefined error: 0
What is wrong with this code ?
How could I get more information about the reason of the failure ?
Related
Reference:
websocket_client_sync_ssl.cpp
// Read a message into our buffer
ws.read(buffer);
// Close the WebSocket connection
ws.close(websocket::close_code::normal);
Based on my test, the ws.close will spit out a warning below:
ERROR message: short read (SSL routines, SSL routines), value:
335544539
Based on this post short read, this error can be safely ignored in the end of the session. I have tried the following method to suppress the warning:
try
{
boost::system::error_code close_ec;
ws.close(websocket::close_code::normal, close_ec);
if (close_ec)
{
std::cerr << "ERROR message: " << close_ec.message() << ", value: " << close_ec.value() << std::endl;
}
}
catch(...)
{
}
However, the ws.close still prints out the warning message.
Question> Is there a way that I can suppress this message?
However, the ws.close still prints out the warning message.
Are you sure? It looks like that's simply coming from the line:
std::cerr << "ERROR message: " << close_ec.message() << ", value: " << close_ec.value() << std::endl;
So, you would check the value of close_ec and conditionally handle it: Short read error-Boost asio synchoronous https call
Also, note that some kinds of "short reads" can constitute security errors. Some of the samples have very insightful comments about this:
// `net::ssl::error::stream_truncated`, also known as an SSL "short read",
// indicates the peer closed the connection without performing the
// required closing handshake (for example, Google does this to
// improve performance). Generally this can be a security issue,
// but if your communication protocol is self-terminated (as
// it is with both HTTP and WebSocket) then you may simply
// ignore the lack of close_notify:
//
// https://github.com/boostorg/beast/issues/38
//
// https://security.stackexchange.com/questions/91435/how-to-handle-a-malicious-ssl-tls-shutdown
//
// When a short read would cut off the end of an HTTP message,
// Beast returns the error beast::http::error::partial_message.
// Therefore, if we see a short read here, it has occurred
// after the message has been completed, so it is safe to ignore it.
if(ec == net::ssl::error::stream_truncated)
ec = {};
else if(ec)
return;
I am using protobuf 3 to serialize a simple message.
I get a bad alloc when i set a string value for one of the memebers of my protobuf message like so.
std::string a("eeee");
hello_in.set_name(a);
The bad alloc exception happens in the libprotobuf.dll in this function...
void CreateInstance(Arena* arena, const ::std::string* initial_value) {
GOOGLE_DCHECK(initial_value != NULL);
// uses "new ::std::string" when arena is nullptr
ptr_ = Arena::Create< ::std::string>(arena, *initial_value);
}
But i think the real problem is that initial_value has been corrupted somehow and has a size of [size] = 3435973836.
Not sure how this is being corrupted. CreateInstance does get called a few times prior to this but its the first time it is called from main.cpp. Which leads me to believe that it has something to do with dll's and ownership of memeory.
Using any of the other set_name functions also cause a bad alloc exception.
Setting the bool or int in the message works fine.
Here is the message and the main.cpp. I didnt include the hello.pb.h/pb.cc as they are quite big but can if it helps.
// See README.txt for information and build instructions.
//
// Note: START and END tags are used in comments to define sections used in
// tutorials. They are not part of the syntax for Protocol Buffers.
//
// To get an in-depth walkthrough of this file and the related examples, see:
// https://developers.google.com/protocol-buffers/docs/tutorials
// [START declaration]
syntax = "proto3";
package commands;
import "google/protobuf/timestamp.proto";
// [END declaration]
// [START messages]
message Hello {
string name = 1;
int32 id = 2; // Unique ID number for this person.
bool on = 3;
google.protobuf.Timestamp last_updated = 4;
}
// [END messages]
#include "hello.pb.h"
// stl
#include <fstream>
#include <iostream>
int main()
{
GOOGLE_PROTOBUF_VERIFY_VERSION;
commands::Hello hello_in;
hello_in.set_id(2);
std::string a("eeee");
hello_in.set_name(a);
hello_in.set_on(false);
{
// Write the new address book back to disk.
std::fstream output("hello.txt", std::ios::out | std::ios::trunc | std::ios::binary);
if (!hello_in.SerializeToOstream(&output)) {
std::cerr << "Failed to write address book." << std::endl;
return -1;
}
}
commands::Hello hello_out;
{
// Read the existing address book.
std::fstream input("hello.txt", std::ios::in | std::ios::binary);
if (!input) {
std::cout << "hello.txt" << ": File not found. Creating a new file." << std::endl;
}
else if (!hello_out.ParseFromIstream(&input)) {
std::cerr << "Failed to parse address book." << std::endl;
return -1;
}
}
// Optional: Delete all global objects allocated by libprotobuf.
google::protobuf::ShutdownProtobufLibrary();
return 0;
}
I have observed same behavior (Visual Studio 2019 C++ project). The solution which helped me: libprotobuf.lib and libprotobuf.dll were replaced in debug/x86 mode by its debug version, libprotobufd.lib and libprotobufd.dll.
I am simiply trying to display a message I receive from a tcp socket which terminates with "\r\n\r\n".
C++ however terminates immediately even though the server indicates that the message has been successfully transmitted.
void handle_read( const boost::system::error_code& error, size_t bytes_transferred)
{
std::istream response_stream(&response_);
std::string incoming;
std::string res_time = make_daytime_string();
while (std::getline(response_stream, incoming) && incoming != "\r")
std::cout << incoming << std::endl;
std::cout <<"message received on "<< res_time <<std::endl;
}
In Eclipse I see the following in consol,
(exit value = -1)
When the program is terminated, If I switch to the consol of Linux I see the following error:
* Error in `/home/administrator/Documents/eclipse/Projects/Asynchronous_TCP/Debug/Asynchronous_TCP': double free or corruption (!prev): 0x0000000001040580 *
Solved
Apperantly I only needed to resolved the socket connection
Now I'm trying to download file from server (Linux) to my host (windows).
It looks working well (other functions) but when I'm trying to read file from server. Data in the file is not proper.
for example)
server text file:
A
B
C
D
E
Reading file and saving to buffer:
A
B
C
I checked small size text file. It was working well. However now I'm in trouble because text file is bigger than before.
Here is my code.
int scp_receive(ssh_session session)
{
ssh_scp scp;
int rc;
int size, mode;
char *filename;
char *buffer;
int fd;
scp = ssh_scp_new(session, SSH_SCP_READ, "/home/abc/27");
if (scp == NULL)
{
fprintf(stderr, "Error allocating scp session: %s\n",
ssh_get_error(session)); return SSH_ERROR;
}
rc = ssh_scp_init(scp);
if (rc != SSH_OK)
{
fprintf(stderr, "Error initializing scp session: %s\n",ssh_get_error(session));
ssh_scp_free(scp);
return rc;
}
rc = ssh_scp_pull_request(scp);
if (rc != SSH_SCP_REQUEST_NEWFILE)
{
fprintf(stderr, "Error receiving information about file: %s\n",ssh_get_error(session));
return SSH_ERROR;
}
size = ssh_scp_request_get_size(scp);
std::cout << "size is:" << size << std::endl;
filename = strdup(ssh_scp_request_get_filename(scp));
mode = ssh_scp_request_get_permissions(scp);
printf("Receiving file %s, size %d, permisssions 0%o\n", filename, size, mode);
free(filename);
buffer = (char *)malloc(sizeof(char)*size);
if (buffer == NULL)
{
fprintf(stderr, "Memory allocation error\n");
return SSH_ERROR;
}
ssh_scp_accept_request(scp);
rc = ssh_scp_read(scp, buffer, sizeof(char)*size);
if(rc == SSH_ERROR)
{
fprintf(stderr, "Error receiving file data: %s\n", ssh_get_error(session));
free(buffer);
return rc;
}
std::cout << buffer << std::endl;
printf("Done\n");
//write(fd, buffer, size);
char path[30];
sprintf(path, "C:/Check/%s", filename);
if (access(path, F_OK) != 0) {
//TODO: file
remove(path);
}
if(0 < (fd=open(path, O_RDWR | O_CREAT | O_TRUNC, mode)))
{
write(fd, buffer, sizeof(char)*size);
close(fd);
}
else
{
std::cerr << "failed to open" << std::endl;
}
free(buffer);
//rc = ssh_scp_pull_request(scp);
//if(rc != SSH_SCP_REQUEST_EOF)
//{
// fprintf(stderr, "Unexpected request: %s\n",ssh_get_error(session));
// return SSH_ERROR;
//}
ssh_scp_close(scp);
ssh_scp_free(scp);
return SSH_OK;
}
The issue here is with the libssh read function. It only reads a max of 65536 bytes at once. It won't read anything large than that block size.
If you take a look at the libssh SCP read function here: http://xtalopt.openmolecules.net/wiki/index.fcgi/browser/src/libssh/scp.c?rev=2b0288492ad2481ee8bdbb8c1f9d5c453a044eee
You will see the size is limited to 65536.
SOLUTION
In your application, you should attempt to read multiple smaller chunks of memory till you finish reading the large text file. And since you have the size of the large text file, this can be done easily via a loop.
I know this is a late answer, but hope this can help someone else having this issue.
I'm using the code posted on http://social.msdn.microsoft.com/Forums/en/vcgeneral/thread/126639f1-487d-4755-af1b-cfb8bb64bdf8 but it doesn't send data just like it says in the first post. How do I use WSAGetLastError() like it says in the solution to find out what's wrong?
I tried the following:
void IRC::SendBuf(char* sendbuf)
{
int senderror = send(m_socket, sendbuf, sizeof(sendbuf), MSG_OOB);
if(senderror == ERROR_SUCCESS) {
printf("Client: The test string sent: \"%s\"\n", sendbuf);
}
else {
cout << "error is: " << senderror << ", WSAGetLastError: " << WSAGetLastError() << endl;
printf("Client: The test string sent: \"%s\"\n", sendbuf);
}
}
And the output is: error is: 4, WSAGetLastError: 0
You're evaluating the address of WSAGetLastError instead of calling it. You need to add parenthesis in order to actually call that function:
void IRC::SendBuf(char* sendbuf)
{
int senderror = send(m_socket, sendbuf, strlen(sendbuf), 0);
if (senderror != SOCKET_ERROR) {
printf("Client: The test string sent: \"%s\"\n", sendbuf);
} else {
cout << "Error is: " << WSAGetLastError() << endl;
}
}
EDIT: The send() function returns the number of bytes written, not an error code. You need to test the return value against SOCKET_ERROR, as in the updated code above. In your case, send() tells that it successfully sent 4 bytes.
As you noted below, it only sends 4 bytes because that's the size of the sendbuf variable (it's a pointer, not a buffer). If the string in sendbuf is null-terminated, you can use strlen() instead. If it isn't, you probably should add a string length parameter to IRC::SendBuf() itself.