I have an java app for blackberry, created with Java Plug-in for Eclipse. I want to invoke a webservice on a webserver through Blackberry mds. The code I am using works, but is not stabile. Meaning that I get successfully get in contact with web server 100 times in a row, but after a while, the connection is broken. The log files from Blackberry are many and not easy to read, but at least I a feel that the phrase "Invalid socket" is not good for me.
I am using StreamConnection class in my code, but I see from some sample code that httpConnection is used instead. Anyone know when to use HttpConnection instead of StreamConnection?
I paste my code here. Perhaps some of you see anything I should have done different:
private boolean sendStatusMessage(String phoneNumber, String status) {
StreamConnection conn = null;
OutputStream output = null; //mari added
try {
String body = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:i3w=\"http://I3WebAction\">"
+ "<soapenv:Header/>"
+ "<soapenv:Body>"
+ "<i3w:I3SetMobileStatus><i3w:p_Status>"
+ status
+ "</i3w:p_Status><i3w:p_PhoneNumber>"
+ phoneNumber
+ "</i3w:p_PhoneNumber>"
+ "</i3w:I3SetMobileStatus></soapenv:Body></soapenv:Envelope>";
String URL = "socket://" + soapServer + ":" + port
+ ";deviceside=false";
conn = (StreamConnection) Connector.open(URL);
//OutputStream output = conn.openOutputStream();
output = conn.openOutputStream();
OutputStreamWriter writer = new OutputStreamWriter(output);
writer.write("POST /SOAPListener/I3SOAPISAPIU.dll HTTP/1.1\r\n");
writer.write("Accept-Encoding: gzip,deflate\r\n");
writer.write("Content-Type: text/xml;charset=UTF-8\r\n");
writer.write("SOAPAction: \"http://I3WebAction/I3SetMobileStatus\"\r\n");
writer.write("User-Agent: Jakarta Commons-HttpClient/3.1\r\n");
writer.write("Host: lvkdb01\r\n");
writer.write("Content-Length: " + body.length() + "\r\n");
writer.write("\r\n");
writer.write(body);
writer.flush();
writer.close(); //mari added
} catch (Exception e) {
Dialog.alert(e.getMessage());
return false;
} finally {
try {
// Close stream regardless of exceptions and return-points
output.close();
} catch (IOException e) {
// If closing the stream causes exception, the stream is most
// likely not open or available. We display an error message,
// and continues the program.
Dialog.alert(e.getMessage());
return false;
}
try {
// Close stream regardless of exceptions and return-points
conn.close();
} catch (IOException e) {
// If closing the stream causes exception, the stream is most
// likely not open or available. We display an error message,
// and continues the program.
Dialog.alert(e.getMessage());
return false;
}
}
return true;
}
I appreciate any comments or ideas on why this code is not running stabile.
By default all requests through BES are transcoded. Try to turn off transcoding and see if that resolves your issue. To turn off transcoding you would need to pass the below header.
Turn off MD transcoding: ("x-rim-transcode-content", "none) as a header
MDS logs would be useful(default location c:\Program Files\Research In Motion\BlackBerryEnterprise Server\Logs)/
They end with “MDAT”. The logging level can be changed by following these instructions.
http://docs.blackberry.com/en/admin/deliverables/14334/Change_logging_level_for_MDSCS_552126_11.jsp
You may also way to enable Verbose HTTP logging for testing, found here, which can help trace through the http messages.
http://docs.blackberry.com/en/admin/deliverables/14334/Change_activities_MDSCS_writes_to_log_827932_11.jsp
Related
I'm working on a project which has to mount samba shares on Ubuntu. This project will be used by non-root users. At now I'm using an application called gvfs-mount because that doesn't require the root password for mounting.
My application runs that executable with specific command line arguments and it works, but the error checking is difficult. I'm using a library called pstreams to launch the gvfs-mount and to write and read to it's stdin/out, but I can predict when the application will write something to stdout. And that is a problem, because if I want to read something from the gvfs-mount's output, but the application doesn't wrote anything, the host application will be blocked, because that will wait for something that will never come.
I know that I could use the mount function from sys/mount.h, but that would require root privileges. My question is: Is there any API, library or tutorial about this topic in C++?
Edit:
As filmor mentioned I had a look to gvfs-mount's source code and I converted to C++. Here is my very basic code:
#include <gtkmm.h>
#include <stdexcept>
#include <iostream>
Glib::RefPtr<Gio::File> file;
Glib::RefPtr<Glib::MainLoop> main_loop;
void on_async_ready(Glib::RefPtr<Gio::AsyncResult>& result)
{
file->mount_enclosing_volume_finish(result);
main_loop->quit();
}
int main()
{
Gio::init();
Glib::init();
main_loop = Glib::MainLoop::create(false);
file = Gio::File::create_for_commandline_arg("smb://192.168.1.3/Memory\\ core");
Glib::RefPtr<Gio::MountOperation> mount_operation = Gio::MountOperation::create();
mount_operation->set_domain("domain");
mount_operation->set_username("user");
mount_operation->set_password("password");
try
{
file->mount_enclosing_volume(mount_operation, &on_async_ready);
}
catch(const Glib::Error& ex)
{
std::cerr << ex.what() << std::endl;
}
main_loop->run();
return 0;
}
The problem is that when I run this code as normal user I get this output:
(process:5816): glibmm-CRITICAL **:
unhandled exception (type Glib::Error) in signal handler:
domain: g-io-error-quark
code : 0
what : Failed to mount Windows share: Operation not permitted
When I run as sudo I get this:
(process:5862): glibmm-CRITICAL **:
unhandled exception (type Glib::Error) in signal handler:
domain: g-io-error-quark
code : 15
what : volume doesn't implement mount
Any suggestion about solving this? The code should work with normal user privileges.
Edit 2:
I updated the source code, because it was an error in uri. I found that if I run the gvfs-mount as sudo, I get the same error message like in my application. So my idea is that there is something wrong with permissions. My username belongs to fuse group it that matters.
#include <gtkmm.h>
#include <iostream>
Glib::RefPtr<Gio::File> file;
Glib::RefPtr<Glib::MainLoop> main_loop;
void on_async_ready(Glib::RefPtr<Gio::AsyncResult>& result)
{
try
{
file->mount_enclosing_volume_finish(result);
}
catch(const Glib::Error& ex)
{
std::cerr << ex.what() << std::endl;
}
main_loop->quit();
}
int main()
{
Gio::init();
Glib::init();
main_loop = Glib::MainLoop::create(false);
file = Gio::File::create_for_commandline_arg("smb://192.168.1.3/Memory core");
Glib::RefPtr<Gio::MountOperation> mount_operation = Gio::MountOperation::create();
mount_operation->set_domain("domain");
mount_operation->set_username("user");
mount_operation->set_password("password");
file->mount_enclosing_volume(mount_operation, &on_async_ready);
main_loop->run();
return 0;
}
I was able to resolve this problem in my Rust application which at first showed the same behaviour as reported in this question.
The solution was to register a callback for the ask-password signal, use this code path to fill in the credentials and then - most importantly - call reply on the mount operation with the Handled flag.
PoC in Rust attached, should transfer easily to C++, too:
use gio::prelude::*;
use glib::{self, clone};
use futures::prelude::*;
use gio::{AskPasswordFlags, MountMountFlags, MountOperation, MountOperationResult};
// read_file taken from https://github.com/gtk-rs/gtk-rs-core/blob/master/examples/gio_futures_await/main.rs#L29
async fn read_file(file: gio::File) -> Result<(), String> {
// Try to open the file.
let strm = file
.read_future(glib::PRIORITY_DEFAULT)
.map_err(|err| format!("Failed to open file: {}", err))
.await?;
// If opening the file succeeds, we asynchronously loop and
// read the file in up to 64 byte chunks and re-use the same
// vec for each read.
let mut buf = vec![0; 64];
let mut idx = 0;
loop {
let (b, len) = strm
.read_future(buf, glib::PRIORITY_DEFAULT)
.map_err(|(_buf, err)| format!("Failed to read from stream: {}", err))
.await?;
// Once 0 is returned, we know that we're done with reading, otherwise
// loop again and read another chunk.
if len == 0 {
break;
}
buf = b;
println!("line {}: {:?}", idx, std::str::from_utf8(&buf[0..len]).unwrap());
idx += 1;
}
// Asynchronously close the stream in the end.
let _ = strm
.close_future(glib::PRIORITY_DEFAULT)
.map_err(|err| format!("Failed to close stream: {}", err))
.await?;
Ok(())
}
// one could probably also use glib to drive the futures
// but this was more familiar to me
#[tokio::main]
async fn main() {
env_logger::init();
let c = glib::MainContext::default();
let file = gio::File::for_uri("smb://host/users/username/Desktop/test.txt");
// check whether the surrounding share is already mounted
let cancellable = gio::Cancellable::new();
if file.find_enclosing_mount(Some(&cancellable)).is_err() {
log::info!("Enclosing share not mounted, trying to mount it");
let mount_op = MountOperation::new();
mount_op.connect_ask_password(|op, msg, default_user, default_domain, flags| {
op.set_anonymous(false);
if flags.contains(AskPasswordFlags::NEED_USERNAME) {
op.set_username(Some("my-user"));
}
if flags.contains(AskPasswordFlags::NEED_PASSWORD) {
op.set_password(Some("my-password"));
}
if flags.contains(AskPasswordFlags::NEED_DOMAIN) {
op.set_domain(Some(default_domain)); // should not be required, let's see
}
// this is the important part!
op.reply(MountOperationResult::Handled);
});
let mount_result = file.mount_enclosing_volume_future(MountMountFlags::empty(), Some(&mount_op));
let mount_result = c.block_on(mount_result);
if let Err(err) = mount_result {
log::error!("Failed to mount: {}", err);
return
}
}
let future = async {
match read_file(file).await {
Ok(()) => (),
Err(err) => eprintln!("Got error: {}", err),
}
};
c.block_on(future);
}
I've been trying to use the mysql++ library in my application (windows x64 based) but I can't seem to connect to my sql server.
Some information:
I used this code to connect to the server:
mysqlpp::Connection conn(db, 0, user, pass, 3306);
this definitely has the right data in it.
and then, my sql server is the standard service from the MySQL install. And I'm pretty sure I used the standard settings. I can connect to it using the MySql Workbench and I edited some new tables and such but my own program doesn't seem to connect.
I read the documentation and I can't find anything specific that might suggest something why I can't connect.
Oh, so many issues, so little time...
Have you checked that your program has permissions to access the database?
Does your program have the correct privileges?
Is your host name correct?
What errors are you getting?
What exception is thrown?
When you use the debugger, what line is the error on?
Here's my method:
sql::Connection * const
Manager ::
get_db_connection(void) const
{
//-------------------------------------------------------------------------
// Use only one connection until proven that more connections will make
// the program more efficient or have a beneficial impact on the user.
// Thus the change in returning sql::Connection * rather than a smart pointer.
// A smart pointer will delete its contents.
//-------------------------------------------------------------------------
static const char host_text[] = "tcp://127.0.0.1:3306/";
static std::string host_name;
if (!m_connection_initialized)
{
host_name = host_text;
initialize_db_driver();
host_name += m_dataset_info.m_dsn_name;
try
{
m_p_connection = m_p_sql_driver->connect(host_name.c_str(),
m_dataset_info.m_user_name.c_str(),
m_dataset_info.m_password.c_str());
}
catch (sql::SQLException &e)
{
/*
The MySQL Connector/C++ throws three different exceptions:
- sql::MethodNotImplementedException (derived from sql::SQLException)
- sql::InvalidArgumentException (derived from sql::SQLException)
- sql::SQLException (derived from std::runtime_error)
*/
wxString wx_text = wxT("# ERR: SQLException in ");
wx_text += wxT(__FILE__);
wxLogDebug(wx_text);
wx_text.Printf(wxT("# ERR: (%s) on line %d"),
__FUNCTION__,
__LINE__);
wxLogDebug(wx_text);
wx_text.Printf(wxT("# ERR: %s (MySQL error code: %d, SQLState: %s)"),
e.what(),
e.getErrorCode(),
e.getSQLState());
wxLogDebug(wx_text);
wxLogDebug(wxT("Verify that mysqlcppconn.dll is in the PATH or in the working directory."));
// throw Manager_Connection_Not_Initialized();
m_connection_initialized = false;
}
catch (...)
{
std::cout << "Unhandled database SQL exception\n" << flush;
m_connection_initialized = false;
}
m_connection_initialized = true;
}
return m_p_connection;
}
So I made a GUI in C++ which calls a child process every time a button is clicked twice. The StandardOutput is redirected, doesn't use ShellExecute.
I made a simple dummy process to test it, let's say dummy.exe, which basically just do this :
void() {
printf("0");
}
And that's all. The process will exit itself after 0 is plotted.
The process is started when a button is clicked, which does this :
private: System::Void bt_getData_Click(System::Object^ sender, System::EventArgs^ e) {
if (bt_getData->Text == "Get Data") {
proc->Start();
bt_getData->Text = "Stop";
}
else if (bt_getData->Text == "Stop") {
bt_getData->Text = "Get Data";
}
}
Then it will read the output using the OutputDataReceived EventHandler.
The problem is when I clicked the button again, the process will be Restarted, but the GUI can't read the new Output.
Case 1 : I cancelled the output read in the OutputDataReceived EventHandler then restart the process, but the next restarted process output can't be read.
private: System::Void outputData(System::Object^ sender, System::Diagnostics::DataReceivedEventArgs^ e) {
x0 = xt;
xt += 1;
if (xt*x_scale > pb_Graph->Width) {
x0 = 0;
xt = 0;
imgTemp = gcnew Bitmap(pb_Graph->Image, 460, 460);
gpcGraph->Clear(Color::Transparent);
}
y0 = yt;
yt = Convert::ToInt16(e->Data);
ret_index++;
if (ret_index > 2047) ret_index = 0;
gpcGraph->DrawLine(greenPen,(float)x0*x_scale,pb_Graph->Height - (float)y0/y_scale - y_null,(float)xt*x_scale,pb_Graph->Height - (float)yt/y_scale - y_null);
pb_Graph->Refresh();
}
After three times restart, this error shows :
An unhandled exception of type 'System.InvalidOperationException' occurred in System.dll
Additional information: An async read operation has already been started on the stream.
Case 2 : I didn't cancel the output read. The same error with case 1 shows, but it is still understandable to me.
Case 3 : I didn't redo the BeginOutputReadLine() when restarting. The error doesn't shown, but the restarted process output can't be read.
My actual goal is to restart the process periodically using a 1 mS timer, so I tested the restart process first using button. But it seems that the newly generated output can't be read.
Any help would be appreciated :)
Okay... I've managed to prevent the errors using different method, which is to call
process->StandardOutput->ReadLine();
This way the async stream reading won't happen.
I already do know, that it is impossible to simply detect if socket is disconnected or not - the server and clients must shout "Can you hear me?" and "Yeah I can." just like we do on skype.
But when boost::asio socket is disconnected from other side I obtain Unhanded exception when trying to read from socket. This is kind of disconnect detection useful enough for me. Can I handle that exception, so instead of crashing, the program will produce message in the console?
Some code for those who need it for everything:
bool SocketClient::read(int bytes, char *text) {
char buffer = 0;
int length = 0;
while(bytes>0) {
size_t len = sock.receive(boost::asio::buffer(&buffer, 1)); //boom: UNHANDLED EXCEPTION
bytes--;
text[length] = buffer;
length++;
}
return true;
}
Because I am connecting to minecraft server, I know when the client is disconnected - exception is caused on any read/write attempt.
try
{
size_t len = sock.receive(boost::asio::buffer(&buffer, 1)); //boom: UNHANDLED EXCEPTION
// More code ...
}
catch (const boost::system::system_error& ex)
{
if ( ex.code() == boost::asio::error::eof )
{
// Work your magic (console logging, retry , bailout etc.)
}
}
Please also take a look at the doc. In the worst case , you could infer the exception type from the debugger :)
I started to program client/server applications in J2ME recently.Now I'm working with c++ builder 2010 indy components (e.g. TidTTCPServer) and J2ME. My application is designed to restart the kerio winroute firewall service from a remote machine.
My server application is written in c++ builder 2010, I've put a TidTCTServer component into a form which binded to 127.0.0.1:4500. That's listening on port 4500 in local machine.
Then i've added a listbox that i need to add every upcoming packets converted to UnicodeString.
//void __fastcall TForm1::servExecute(TIdContext *AContext)
UnicodeString s;
UnicodeString txt;
txt=Trim(AContext->Connection->IOHandler->ReadLn());
otvet->Items->Add(txt);
otvet->ItemIndex=otvet->Items->Count-1;
if (txt=="1") {
AContext->Connection->IOHandler->WriteLn("Suhrob");
AContext->Connection->Disconnect();
}
if (txt=="2") {
AContext->Connection->IOHandler->WriteLn("Shodi");
AContext->Connection->Disconnect();
}
//----------------------------------------------------------------------------
// void __fastcall TForm1::servConnect(TIdContext *AContext)
++counter;
status->Panels->Items[0]->Text="Connections:" + IntToStr(counter);
status->Panels->Items[1]->Text="Connected to " + AContext->Connection->Socket->Binding->PeerIP + ":" + AContext->Connection->Socket->Binding->PeerPort;
and my client side code looks smth like this:
else if (command == send) {
// write pre-action user code here
InputStream is=null;
OutputStream os=null;
SocketConnection client=null;
ServerSocketConnection server=null;
try {
server = (ServerSocketConnection) Connector.open("socket://"+IP.getString()+":"+PORT.getString());
// wait for a connection
client = (SocketConnection) Connector.open("socket://"+IP.getString()+":"+PORT.getString());
// set application-specific options on the socket. Call setSocketOption to set other options
client.setSocketOption(SocketConnection.DELAY, 0);
client.setSocketOption(SocketConnection.KEEPALIVE, 0);
is = client.openInputStream();
os = client.openOutputStream();
// send something to server
os.write("texttosend".getBytes());
// read server response
int c = 0;
while((c = is.read()) != -1) {
// do something with the response
System.out.println((char)c);
}
// close streams and connection
}
catch( ConnectionNotFoundException error )
{
Alert alert = new Alert(
"Error", "Not responding!", null, null);
alert.setTimeout(Alert.FOREVER);
alert.setType(AlertType.ERROR);
switchDisplayable(alert, list);
}
catch (IOException e)
{
Alert alert = new Alert("ERror", e.toString(), null, null);
alert.setTimeout(Alert.FOREVER);
alert.setType(AlertType.ERROR);
switchDisplayable(alert, list);
e.printStackTrace();
}
finally {
if (is != null) {
try {
is.close();
} catch (Exception ex) {
System.out.println("Failed to close is!");
}
try {
os.close();
} catch (Exception ex) {
System.out.println("Failed to close os!");
}
}
if (server != null) {
try {
server.close();
} catch (Exception ex) {
System.out.println("Failed to close server!");
}
}
if (client != null) {
try {
client.close();
} catch (Exception ex) {
System.out.println("Failed to close client!");
}
}
}
my client application gets connected with the server but when i try to send data such as
os.write("texttosend".getBytes());
I cannot get text data on the server using. That's I am not getting sent packets in the server from client.
txt=Trim(AContext->Connection->IOHandler->ReadLn());
Guys, where am I wrong? is the way i'm doing is ok?
Or do I need to use StreamConnection instead of SocketConnection?
And when i use telnet to send data it works cool, strings will be added to listbox
telnet 127.0.0.1 4500
texttosend
23
asf
Any help is appreciated !!!
Thanks in advance!
The main problem is that you are using ReadLn() on the server end. ReadLn() does not exit until a data terminator is encountered (a LF line break character is the default terminator) or if a reading timeout occurs (Indy uses infinite timeouts by default). Your J2ME code is not sending any data terminator, so there is nothing to tell ReadLn() when to stop reading. The reason it works with Telnet is because it does send line break characters.
The other problem with your code is that TIdTCPServer is a multi-threaded component, but your code is updating the UI components in a thread-unsafe manner. You MUST synchronize with the main thread, such as by using Indy's TIdSync and/or TIdNotify classes, in order to update your UI safely from inside of the server's event handlers.
Yes, flush method is necessary to call after sending bytes, but ..... finally....
then i tried to include my connection code in a new thread that implements Runnable worked perfectly. Now I've found where I was wrong!!!!!!!!!!!!!!
That's guys you need to include above code in the following block.
Thread t= new Thread(this);
t.start();
public void run()
{
//here paste the code
}
Try OutputStream.flush()?
If not, try writing to a known working server, instead of one you've created yourself (something like writing "HELO" to an SMTP server), this will help you figure out which end the error is at.