Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Java Development

Reply
New Developer
Posts: 13
Registered: ‎08-03-2009
My Device: Not Specified

HttpConnection error codes

Hello everybody!

I'm currently trying to develop an intelligent search-client that pulls information from a server and displays it - normally a rather easy task. With BlackBerry, however, there seems to be just no way to get this done. I must have read almost every shred documentation in the knowledge base and peter's excellent post about connections - but still no success. Sometimes I'm able to establish connections with one of the various appendices, but never for long...
This is frustrating enough - but the real showstopper for me is that there are always these cryptic messages in the log without any hints to what these could mean: Is there a list somewhere that explains what the error "net.rim.tcp TNLf 0" means? Or what am I supposed to do if there is a "net.rim.tcp OPsx -1" in the log? 

Of course, in the simulator this all works well, which makes the testing process even more frustrating (rapc/sign/deploy)...

I would be very grateful if anybody had an idea how to tackle this problem!

Thanks in advance,
KoMaXX
New Developer
Posts: 13
Registered: ‎08-03-2009
My Device: Not Specified

Re: HttpConnection error codes

Hello again,

I got it now boiled down to the following error-case:

* I create a few HttpConnections via the direct tcp-stack (";deviceside=true") and get content without any trouble
* Suddenly, without any obvious triggering event and after different amounts of time there is the error "E net.rim.tcp - OPsx -1" shows up in the log
* From this point on all connection attempts fail with "General socket error".

This behavior only appears on the two devices I test on (9000 4.6.0.247 / 8900 4.6.1.133) and not in simulator. The carrier is T-Mobile Germany.

KoMaXX

Developer
Posts: 176
Registered: ‎11-06-2008
My Device: Not Specified

Re: HttpConnection error codes

[ Edited ]

can you post your network connection code

 

specifically the logic you use to decide what URL appenders to use and when you open the http connection

 

also, are you properly handling the closing of input/output streams and connection objects?

Message Edited by jhw1701 on 08-03-2009 12:51 PM
Developer
Posts: 905
Registered: ‎02-07-2009
My Device: BlackBerry Torch 9800
My Carrier: Globe Telecom

Re: HttpConnection error codes

don't you encounter any exceptions? because from my experience, once i encountered an error in direct tcp, i need to turn off then turn on the mobile network. I'll look for my notes, i forgot the exception message. 
New Developer
Posts: 13
Registered: ‎08-03-2009
My Device: Not Specified

Re: HttpConnection error codes

Thank you very much for the replies Smiley Happy

@johnbibs
Yes, there are exceptions when I try to open the connection: It is a IOException with the message "general socket error". Turning the mobile network off and on helps? Can this be done per software or do I need to beg my users to please do that?

@jhw1701
The connection code is below (sorry, it's rather lengthy). Currently, I just try different suffixes until one works. I handle closing of streams and connections - but I can't say if it is done "properly"...

 

public class RimHttpRequestor implements IHttpRequestor { private String lastSuccessfulSuffix = ""; // bugix approach: Allow only one connection at a time private static Object mutexer = new Object(); private Vector createPrioritizedSuffixes(String basicURL) throws IOException{ ServiceBook sb = ServiceBook.getSB(); ServiceRecord[] serviceRecords = sb.getRecords(); Vector ret = new Vector(); if (basicURL == null || basicURL.length() < 1 || basicURL.indexOf(':') < 0){ throw new IOException("[RimHttpRequestor] illegal base url: " + basicURL); } // first: the last successful connection: ret.addElement(lastSuccessfulSuffix); // let the device figure out itself what to do ret.addElement(""); String tmp = getDirectTcpAppendix(serviceRecords); if (tmp != null && tmp.length() > 0) ret.addElement(tmp); tmp = getMDSAppendix(serviceRecords); if (tmp != null && tmp.length() > 0) ret.addElement(tmp); tmp = getWap2Appendix(serviceRecords); if (tmp != null && tmp.length() > 0) ret.addElement(tmp); tmp = getWifiAppendix(serviceRecords); if (tmp != null && tmp.length() > 0) ret.addElement(tmp); return ret; } private String getMDSAppendix(ServiceRecord[] serviceRecords) { return ";deviceside=false"; } private String getWap2Appendix(ServiceRecord[] serviceRecords){ ServiceRecord current; for (int i = 0; i < serviceRecords.length; i++){ current = serviceRecords[i]; if ( !current.getCid().equalsIgnoreCase("WPTCP") || current.getUid() == null || current.getUid().length() <= 0 || !current.isValid() || current.isDisabled() || current.getUid().toLowerCase().indexOf("mms") >= 0 || current.getUid().toLowerCase().indexOf("wifi") >= 0) continue; return ";deviceside=true;ConnectionUID=" + current.getUid(); } return null; } private String getDirectTcpAppendix(ServiceRecord[] serviceRecords){ // It would be nice to specify apn's directly. However, this seems impossible... return ";deviceside=true"; } private String getWifiAppendix(ServiceRecord[] serviceRecords){ return ";interface=wifi"; } public String[] httpRequestGET(String url) throws IOException { synchronized (mutexer) { HttpConnection con = null; String[] ret = null; Vector suffixes = createPrioritizedSuffixes(url); for (int i = 0; i < suffixes.size(); i++){ try { con = (HttpConnection) Connector.open(url + (String) suffixes.elementAt(i), Connector.READ_WRITE); ret = doRequestGET(con); con.close(); if (ret == null || ret.length < 1) continue; lastSuccessfulSuffix = (String) suffixes.elementAt(i); return ret; } catch (IOException e){ Log.log("[RimHttpRequestor] connecting per "+(url + suffixes.elementAt(i))+" failed: " + e.getMessage()); } finally { try { if (con != null) con.close(); } catch (Exception e){ Log.log("[RimHttpRequestor] Exception when closing connection: "+e.getMessage()); } } } if (ret == null) throw new IOException("[RimHttpRequestor] all access methods failed."); return ret; } } /** * Executes a http-request with the given headers. The response-headers are delivered through * the parameter <code>headers</code>. */ public String[] httpRequestGET(String url, HttpHeaders headers) throws IOException { synchronized (mutexer) { if (headers == null) throw new IllegalArgumentException("[RimHttpRequestor]<get> headers are not allowed to be null!"); HttpConnection con = null; String[] ret = null; Vector suffixes = createPrioritizedSuffixes(url); for (int i = 0; i < suffixes.size(); i++){ try { con = (HttpConnection) Connector.open(url + (String)suffixes.elementAt(i), Connector.READ_WRITE); int size = headers.size(); for (int j = 0; j < size; j++) { con.setRequestProperty(headers.getPropertyKey(j), headers.getPropertyValue(j)); } ret = doRequestGET(con); con.close(); if (ret == null || ret.length < 1) continue; lastSuccessfulSuffix = (String) suffixes.elementAt(i); // store the headers: headers.reset(); String key = con.getHeaderFieldKey(0); String value = con.getHeaderField(0); for (int j = 1; key != null; j++){ headers.addProperty(key, value); key = con.getHeaderFieldKey(j); value = con.getHeaderField(j); } return ret; } catch (IOException e){ Log.log("[RimHttpRequestor] connecting per "+ (url + suffixes.elementAt(i)) + " failed: " + e.getMessage()); } finally { try { if (con != null) con.close(); } catch (Exception e){ Log.log("[RimHttpRequestor] Exception when closing connection: "+e.getMessage()); } } } if (ret == null) throw new IOException("[RimHttpRequestor] all access methods failed."); return ret; } } private String[] doRequestGET(HttpConnection con) throws IOException{ con.setRequestMethod(HttpConnection.GET); InputStream is = con.openInputStream(); Vector temp = new Vector(); StringBuffer sb = new StringBuffer(); int chr; while ((chr = is.read()) != -1) { if ((char) chr != '\n') { sb.append((char) chr); } else { temp.addElement(sb.toString()); sb.setLength(0); } } // don't forget the last part: if (sb.length() > 0){ temp.addElement(sb.toString()); } is.close(); String[] retStrings = new String[temp.size()]; for (int i = 0; i < temp.size(); i++) { retStrings[i] = (String) temp.elementAt(i); } return retStrings; } public byte[] httpRequestRaw(String urlString) throws IOException { synchronized (mutexer) { HttpConnection con = null; byte[] ret = null; Vector suffixes = createPrioritizedSuffixes(urlString); for (int i = 0; i < suffixes.size(); i++){ try { con = (HttpConnection) Connector.open(urlString + (String)suffixes.elementAt(i), Connector.READ_WRITE); ret = doRequestRaw(con); con.close(); if (ret == null) continue; lastSuccessfulSuffix = (String) suffixes.elementAt(i); return ret; } catch (IOException e){ Log.log("[RimHttpRequestor] connecting per "+ (urlString + suffixes.elementAt(i)) + " failed: " + e.getMessage()); } finally { try { if (con != null) con.close(); } catch (Exception e) { Log.log("[RimHttpRequestor] Exception when closing connection: "+e.getMessage()); } } } if (ret == null) throw new IOException("[RimHttpRequestor] all access methods failed."); return ret; } } private byte[] doRequestRaw(HttpConnection con) throws IOException{ con.setRequestMethod(HttpConnection.GET); InputStream is = con.openInputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[16128]; int result = is.read(buffer); while (result != -1) { baos.write(buffer, 0, result); result = is.read(buffer); } is.close(); byte[] retBytes = baos.toByteArray(); baos.close(); return retBytes; } }

 

 

New Developer
Posts: 13
Registered: ‎08-03-2009
My Device: Not Specified

Re: HttpConnection error codes

Sorry, this code looks like a mess. I'll reformat and re-post it in a minute!
New Developer
Posts: 13
Registered: ‎08-03-2009
My Device: Not Specified

Re: HttpConnection error codes

The same code, hopefully better readable... 

 

public class RimHttpRequestor implements IHttpRequestor { private String lastSuccessfulSuffix = ""; // bugix approach: Allow only one connection at a time private static Object mutexer = new Object(); private Vector createPrioritizedSuffixes(String basicURL) throws IOException{ ServiceBook sb = ServiceBook.getSB(); ServiceRecord[] serviceRecords = sb.getRecords(); Vector ret = new Vector(); if ( basicURL == null || basicURL.length() < 1 || basicURL.indexOf(':') < 0){ throw new IOException( "[RimHttpRequestor] illegal base url: " + basicURL ); } // first: the last successful connection: ret.addElement(lastSuccessfulSuffix); // let the device figure out itself what to do ret.addElement(""); ret.addElement(getDirectTcpAppendix()); ret.addElement(getMDSAppendix()); String tmp = getWap2Appendix(serviceRecords); if (tmp != null && tmp.length() > 0){ ret.addElement(tmp); } ret.addElement(getWifiAppendix()); return ret; } private String getMDSAppendix() { return ";deviceside=false"; } private String getWap2Appendix( ServiceRecord[] serviceRecords){ ServiceRecord current; for (int i = 0; i < serviceRecords.length; i++){ current = serviceRecords[i]; if (!current.getCid().equalsIgnoreCase("WPTCP") || current.getUid() == null || current.getUid().length() <= 0 || !current.isValid() || current.isDisabled() || current.getUid().toLowerCase().indexOf("mms") >= 0 || current.getUid().toLowerCase().indexOf("wifi") >= 0) continue; return ";deviceside=true;ConnectionUID=" + current.getUid(); } return null; } private String getDirectTcpAppendix(){ // It would be nice to specify apn's directly. // However, this seems impossible... return ";deviceside=true"; } private String getWifiAppendix(){ return ";interface=wifi"; } public String[] httpRequestGET(String url) throws IOException { synchronized (mutexer) { HttpConnection con = null; String[] ret = null; Vector suffixes = createPrioritizedSuffixes(url); for (int i = 0; i < suffixes.size(); i++){ try { con = (HttpConnection) Connector.open( url + (String) suffixes.elementAt(i), Connector.READ_WRITE); ret = doRequestGET(con); con.close(); if (ret == null || ret.length < 1) continue; lastSuccessfulSuffix = (String) suffixes.elementAt(i); return ret; } catch (IOException e){ Log.log("[RimHttpRequestor] connecting per " +(url + suffixes.elementAt(i)) +" failed: " + e.getMessage()); } finally { try { if (con != null) con.close(); } catch (Exception e){ Log.log("[RimHttpRequestor] Exception when closing connection: "+e.getMessage()); } } } if (ret == null){ throw new IOException( "[RimHttpRequestor] all access methods failed."); } return ret; } } /** * Executes a http-request with the given headers. * The response-headers are delivered through * the parameter <code>headers</code>. */ public String[] httpRequestGET( String url, HttpHeaders headers) throws IOException { synchronized (mutexer) { if (headers == null) throw new IllegalArgumentException( "[RimHttpRequestor]<get> headers are not allowed to be null!"); HttpConnection con = null; String[] ret = null; Vector suffixes = createPrioritizedSuffixes(url); for (int i = 0; i < suffixes.size(); i++){ try { con = (HttpConnection) Connector.open( url + (String)suffixes.elementAt(i), Connector.READ_WRITE); int size = headers.size(); for (int j = 0; j < size; j++) { con.setRequestProperty( headers.getPropertyKey(j), headers.getPropertyValue(j) ); } ret = doRequestGET(con); con.close(); if (ret == null || ret.length < 1) continue; lastSuccessfulSuffix = (String) suffixes.elementAt(i); // store the headers: headers.reset(); String key = con.getHeaderFieldKey(0); String value = con.getHeaderField(0); for (int j = 1; key != null; j++){ headers.addProperty(key, value); key = con.getHeaderFieldKey(j); value = con.getHeaderField(j); } return ret; } catch (IOException e){ Log.log( "[RimHttpRequestor] connecting per " +(url + suffixes.elementAt(i)) +" failed: " + e.getMessage()); } finally { try { if (con != null) con.close(); } catch (Exception e){ Log.log( "[RimHttpRequestor] Exception when closing connection: " +e.getMessage()); } } } if (ret == null){ throw new IOException( "[RimHttpRequestor] all access methods failed."); } return ret; } } private String[] doRequestGET(HttpConnection con) throws IOException{ con.setRequestMethod(HttpConnection.GET); InputStream is = con.openInputStream(); Vector temp = new Vector(); StringBuffer sb = new StringBuffer(); int chr; while ((chr = is.read()) != -1) { if ((char) chr != '\n') { sb.append((char) chr); } else { temp.addElement(sb.toString()); sb.setLength(0); } } // don't forget the last part: if (sb.length() > 0){ temp.addElement(sb.toString()); } is.close(); String[] retStrings = new String[temp.size()]; for (int i = 0; i < temp.size(); i++) { retStrings[i] = (String) temp.elementAt(i); } return retStrings; } public byte[] httpRequestRaw(String urlString) throws IOException { synchronized (mutexer) { HttpConnection con = null; byte[] ret = null; Vector suffixes = createPrioritizedSuffixes(urlString); for (int i = 0; i < suffixes.size(); i++){ try { con = (HttpConnection) Connector.open( urlString + (String)suffixes.elementAt(i), Connector.READ_WRITE); ret = doRequestRaw(con); con.close(); if (ret == null) continue; lastSuccessfulSuffix = (String) suffixes.elementAt(i); return ret; } catch (IOException e){ Log.log("[RimHttpRequestor] connecting per " +(urlString + suffixes.elementAt(i)) +" failed: " + e.getMessage()); } finally { try { if (con != null) con.close(); } catch (Exception e) { Log.log("[RimHttpRequestor] Exception when closing connection: "+e.getMessage()); } } } if (ret == null){ throw new IOException( "[RimHttpRequestor] all access methods failed."); } return ret; } } private byte[] doRequestRaw(HttpConnection con) throws IOException{ con.setRequestMethod(HttpConnection.GET); InputStream is = con.openInputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[16128]; int result = is.read(buffer); while (result != -1) { baos.write(buffer, 0, result); result = is.read(buffer); } is.close(); byte[] retBytes = baos.toByteArray(); baos.close(); return retBytes; } }

 

 

 

 

 

Developer
Posts: 176
Registered: ‎11-06-2008
My Device: Not Specified

Re: HttpConnection error codes

closing the connection and input stream is done properly

 

I would suggest checking the coverage before connecting to the various network routes.

 

when I make a network connection I check many things before I ever attempt to open the connection, here's what I test

 

int radioState = RadioInfo.getState();
if (radioState == RadioInfo.STATE_OFF)
{
    //report the error
    return;
}
if (radioState == RadioInfo.STATE_LOWBATT)
{
    //report the error
    return;
}

int radioSignal = RadioInfo.getSignalLevel();
if (radioSignal == RadioInfo.LEVEL_NO_COVERAGE)
{
    //report the error
    return;
}

if (CoverageInfo.isOutOfCoverage())
{
    //report the error
    return;
}


Then before trying each network type check with CoverageInfo to make sure coverage is sufficient for whatever connection type you are about to try. Here's a snippet of code but you can use different COVERAGE_XXX flags for BIS and Direct TCP.

if(CoverageInfo.isCoverageSufficient(CoverageInfo.COVERAGE_MDS))
{
    //continue making the http call
}
else
{
    //report the insufficient coverage
}

Developer
Posts: 176
Registered: ‎11-06-2008
My Device: Not Specified

Re: HttpConnection error codes

[ Edited ]

and on a side note I believe you are not using the wifi appender properly

 

when a device is making the connection over MDS or BIS-B and there's a wifi connection it uses wifi automatically (even if you don't add the interface=wifi appender flag)

 

but when you try direct TCP you have to specify the flag if you want it to use wifi.

 

here's what I do when I'm going to route a connection over tcp

if (CoverageInfo.isCoverageSufficient(CoverageInfo.COVERAGE_DIRECT))
{
appenders.addElement(";deviceside=true");

if (Utilities.isOnWLAN())
{
appenders.addElement(";interface=wifi");
}
}



//helper function from a utilities class
static boolean isOnWLAN()
{
if (RadioInfo.areWAFsSupported(RadioInfo.WAF_WLAN) && WLANInfo.getWLANState() == WLANInfo.WLAN_STATE_CONNECTED)
{
return (true);
}
return (false);
}

 

 

in my code I iterate over the appenders Vector and turn it into one string of appenders to add to the URL passed to the Connector class.

Message Edited by jhw1701 on 08-04-2009 04:43 AM
New Developer
Posts: 13
Registered: ‎08-03-2009
My Device: Not Specified

Re: HttpConnection error codes

Thank you very, very much!
I will incorporate these excellent suggestions into my code immediately!

Do you think, these changes should help me with my original "OPsx -1" / "General socket error" problem?