Forums | developer.brewmp.com Forums | developer.brewmp.com

Developer

Forums

Forums:

I'm seeing a consisten problem with closing and reopening sockets.

I open a UDP socket and exchange some data. Then I give a command to the application and it closes the socket with ISOCKET_Release() and cancels all callbacks, so I can do some stuff "offline." When I give the command to go back "online", INETMGR_OpenSocket() returns a non-zero value, in fact the same value as the previous call, at least sometimes, so its reusing the memory, but attempts to read always fail. BREW 1.1 gives AEE_NET_EBADF and the BREW 2.0 emulator gives AEE_NET_EINVAL.

The interesting thing is that if I wait 30 seconds before hitting the key to go "online", it works. I get logged back in just fine and can play.

It sure looked like a linger time issue, and I tried to work around it by setting the linger time down, but I read somewhere that either it'll fail True BREW or the carriers will flunk it if it changes the linger time, so that's no answer.

Any ideas? If necessary, I'll put something in the application forcing the user to wait 30 seconds before going back "online", but thats pretty ugly.

Kelton

What I suggest you to do is try and release all related objects and recreate them with each network access.
What you mentioned here is the default 30 sec network linger time. You can find some information about it in this forum and in the API docs.
Linger time is the time a network object resides in memory before releasing the socket.
Try looking into the INETMGR_SetLinger(). You might find an answer there.
Sorry for the fag response but this is the most I know about it.
Guy

What I suggest you to do is try and release all related objects and recreate them with each network access.
What you mentioned here is the default 30 sec network linger time. You can find some information about it in this forum and in the API docs.
Linger time is the time a network object resides in memory before releasing the socket.
Try looking into the INETMGR_SetLinger(). You might find an answer there.
Sorry for the fag response but this is the most I know about it.
Guy

Quote:Originally posted by kelton
but attempts to read always fail
Are you calling RecvFrom() before SendTo()? If so, did you Bind() the socket again?

Quote:Originally posted by kelton
but attempts to read always fail
Are you calling RecvFrom() before SendTo()? If so, did you Bind() the socket again?

Yes, receive is getting called first. I'm not using Bind since this is UDP.

Yes, receive is getting called first. I'm not using Bind since this is UDP.

You need to bind first, or you won't have a port for your server to send data to. Also, how does your server know the IP address?

You need to bind first, or you won't have a port for your server to send data to. Also, how does your server know the IP address?

The bind was happening implicitly by the ReadFrom, I think. I'm putting in the explicit ISOCKET_Bind, as discussed in the other thread :) That may clear up some of the fog.
The server learns the phone's address and port when it receives the first packet from the phone, so data traffic DOES start with a packet sent by the phone.
There's a bit of a tectonic shift in thought process going on, since I'm used to only using an explicit bind call when setting up a server, but BREW is different :)
Kelton

The bind was happening implicitly by the ReadFrom, I think. I'm putting in the explicit ISOCKET_Bind, as discussed in the other thread :) That may clear up some of the fog.
The server learns the phone's address and port when it receives the first packet from the phone, so data traffic DOES start with a packet sent by the phone.
There's a bit of a tectonic shift in thought process going on, since I'm used to only using an explicit bind call when setting up a server, but BREW is different :)
Kelton

If you use RecvFrom() before SendTo(), then you are acting as a server and need to explicitly Bind(). If you are really a client, then use SendTo() first, and there is no need to Bind().

If you use RecvFrom() before SendTo(), then you are acting as a server and need to explicitly Bind(). If you are really a client, then use SendTo() first, and there is no need to Bind().

That makes sense.

That makes sense.

I'm beginning to suspect that the problem has something to do with UDP, since the DNS operations, which use TCP, don't seem to exhibit the inability to operate after a quick close/reopen. Or maybe it's a subtle bug in something I'm doing. :(
Kelton

I'm beginning to suspect that the problem has something to do with UDP, since the DNS operations, which use TCP, don't seem to exhibit the inability to operate after a quick close/reopen. Or maybe it's a subtle bug in something I'm doing. :(
Kelton

FYI, most DNS clients, including BREW, use UDP exclusively. TCP is typically only used by secondary DNS servers to sync entire zones with the master.
Assuming you program is a client, here is the sequence you should be following:
Create INetMgr
GetHostByName()
OpenSocket(); you can now release the INetMgr
SendTo(); may need to repeat with Writeable()
RecvFrom(); may need to repeat with Readable()
At this point, you can repeat the last two steps indefinitely. There is no reason to close the socket until your program exits. BREW will only keep the network up if you have a Readable callback registered, which you won't in your "offline" state.

FYI, most DNS clients, including BREW, use UDP exclusively. TCP is typically only used by secondary DNS servers to sync entire zones with the master.
Assuming you program is a client, here is the sequence you should be following:
Create INetMgr
GetHostByName()
OpenSocket(); you can now release the INetMgr
SendTo(); may need to repeat with Writeable()
RecvFrom(); may need to repeat with Readable()
At this point, you can repeat the last two steps indefinitely. There is no reason to close the socket until your program exits. BREW will only keep the network up if you have a Readable callback registered, which you won't in your "offline" state.

Ah ha! That did it!
I was assuming that I should release the socket and net manager when I went "offline". It does make sense, and it was recommended here by someone.
So I changed it so that I never release the socket or net manager, until application shutdown of course. Turning off the readable does the trick: if I wait 45 seconds then go back "online", I get a NE_PPP event telling me NET_PPP_OPEN, then data starts to flow. I can hop "offline" then back "online" repeatedly and quickly, no problem so far as BREW is concerned, all that's really happening is the readable going on and off and some state variables changing.
Curiously, I don't get the NE_PPP event when the link goes down, but maybe thats an artifact of the emulator.
This threw a real crimp in the server, though. I was counting on the IP address:port number changing between "sessions" for the packets received at the server, which was happening when I released the socket and recreated it. Now that the phone (or emulator) keeps the socket around, the port number of the client does not change, so I can't key off that as part of session identification. The server has to get smarter and more robust about sudden unexpected changes in packet contexts, but smarter and more robust is always good.
I still don't understand why the other way wasn't working right, but I now have something that works 100% and is understood.
Thanks!
Kelton

Ah ha! That did it!
I was assuming that I should release the socket and net manager when I went "offline". It does make sense, and it was recommended here by someone.
So I changed it so that I never release the socket or net manager, until application shutdown of course. Turning off the readable does the trick: if I wait 45 seconds then go back "online", I get a NE_PPP event telling me NET_PPP_OPEN, then data starts to flow. I can hop "offline" then back "online" repeatedly and quickly, no problem so far as BREW is concerned, all that's really happening is the readable going on and off and some state variables changing.
Curiously, I don't get the NE_PPP event when the link goes down, but maybe thats an artifact of the emulator.
This threw a real crimp in the server, though. I was counting on the IP address:port number changing between "sessions" for the packets received at the server, which was happening when I released the socket and recreated it. Now that the phone (or emulator) keeps the socket around, the port number of the client does not change, so I can't key off that as part of session identification. The server has to get smarter and more robust about sudden unexpected changes in packet contexts, but smarter and more robust is always good.
I still don't understand why the other way wasn't working right, but I now have something that works 100% and is understood.
Thanks!
Kelton

A further wrinkle. ISOCKET_Readable has far greater implications than one might think.
My original sequence was:
1) Open socket.
2) perform DNS lookup.
3) When DNS responds, set readable and start sending data. Note that I *know* no data will come in until I get the DNS reply, so why bother to set the readable yet?
That sequence did not work, produced error 538 from the socket forever. So I used INETMGR_Notify() to see when the PPP came up, issued the DNS then, then set readable when I got the DNS reply. It worked, but a little cumbersome.
Then the lightbulb went on. I moved the ISOCKET_Readable to right after the socket open, then make the DNS call. Viola! No waiting for the PPP to come up! No wierd sequencing of events!
ISOCKET_Readable apparently does a lot more than register a callback. It seems to bring the socket to life.
Kelton

A further wrinkle. ISOCKET_Readable has far greater implications than one might think.
My original sequence was:
1) Open socket.
2) perform DNS lookup.
3) When DNS responds, set readable and start sending data. Note that I *know* no data will come in until I get the DNS reply, so why bother to set the readable yet?
That sequence did not work, produced error 538 from the socket forever. So I used INETMGR_Notify() to see when the PPP came up, issued the DNS then, then set readable when I got the DNS reply. It worked, but a little cumbersome.
Then the lightbulb went on. I moved the ISOCKET_Readable to right after the socket open, then make the DNS call. Viola! No waiting for the PPP to come up! No wierd sequencing of events!
ISOCKET_Readable apparently does a lot more than register a callback. It seems to bring the socket to life.
Kelton

Yup. From BREW's perspective, a "readable" UDP socket is treated much like a connected TCP socket: data can come from the other end at any time, so BREW needs to make sure the network is available.

Yup. From BREW's perspective, a "readable" UDP socket is treated much like a connected TCP socket: data can come from the other end at any time, so BREW needs to make sure the network is available.

To summarize, this sequence of events works perfectly, i.e. can star and stop as fast as fast as you want, can tear down and reconnect (in response to app suspend/resume) as fast as you want:
1. Instantiate net manager.
2. Set up INETMGR_OnEvent if you want.
3. Use net manager to open the UDP socket.
4. Use ISOCKET_Readable to register the callback and activate the socket.
5. Use ISOCKET_Bind to bind the UDP socket to a local port. I use 0, because I don't care what particular port it uses.
6. Set up the DNS callback and call INETMGR_GetHostByName to get the address of the destination.
7. When the DNS callback fires, grab the address and begin data transmission to the server.
To go "offline", just cancel the readable.
To go back "online", re-set the readable.
To shut down, like in response to a suspend event or on application exit, cancel the readable, then release the socket and net manager, cancelling the OnEvent if you are using it.
Resuming after a suspend just involves starting the process from the top.
It may be necessary to check the return on ISOCKET_Bind and use a "writeable" to retry it. Doesn't seem necessary on the emulator, will check it when I get my phone back next week.
See, I knew there was a perfect sequence of events, just finding it was tricky :)
Kelton

To summarize, this sequence of events works perfectly, i.e. can star and stop as fast as fast as you want, can tear down and reconnect (in response to app suspend/resume) as fast as you want:
1. Instantiate net manager.
2. Set up INETMGR_OnEvent if you want.
3. Use net manager to open the UDP socket.
4. Use ISOCKET_Readable to register the callback and activate the socket.
5. Use ISOCKET_Bind to bind the UDP socket to a local port. I use 0, because I don't care what particular port it uses.
6. Set up the DNS callback and call INETMGR_GetHostByName to get the address of the destination.
7. When the DNS callback fires, grab the address and begin data transmission to the server.
To go "offline", just cancel the readable.
To go back "online", re-set the readable.
To shut down, like in response to a suspend event or on application exit, cancel the readable, then release the socket and net manager, cancelling the OnEvent if you are using it.
Resuming after a suspend just involves starting the process from the top.
It may be necessary to check the return on ISOCKET_Bind and use a "writeable" to retry it. Doesn't seem necessary on the emulator, will check it when I get my phone back next week.
See, I knew there was a perfect sequence of events, just finding it was tricky :)
Kelton

I declared victory too soon.
Checking the return on ISOCKET_Bind and using ISOCKET_Writeable was a good thing. It didn't appear to change the behavior, but it worked and resulted in a ISOCKET_Bind that was happy.
All that was under the BREW 2.0 emulator.
Under the BREW 1.1 emulator, everything works until I provoke a suspend event. The socket and net manager are released, everthing cancelled. When I go back "online" after the resume, The net manager and socket are recreated, and ISOCKET_ Bind returns success, not "would block", but all subsequent attempts to read return 514. If I wait 30 seconds before going "online", it works.
Sigh.
Maybe its an artifact of the 1.1 emulator. I should be so lucky.
Kelton

I declared victory too soon.
Checking the return on ISOCKET_Bind and using ISOCKET_Writeable was a good thing. It didn't appear to change the behavior, but it worked and resulted in a ISOCKET_Bind that was happy.
All that was under the BREW 2.0 emulator.
Under the BREW 1.1 emulator, everything works until I provoke a suspend event. The socket and net manager are released, everthing cancelled. When I go back "online" after the resume, The net manager and socket are recreated, and ISOCKET_ Bind returns success, not "would block", but all subsequent attempts to read return 514. If I wait 30 seconds before going "online", it works.
Sigh.
Maybe its an artifact of the 1.1 emulator. I should be so lucky.
Kelton

I don't understand your step 4 in the previous post. What are you trying to achieve by calling Readable() when there is no data expected? You should not call Readable() until after you have used SendTo() and are expecting data back from your server.
Also, since your app is a client, there is no need for step 5 - BREW will implicitly bind to port zero when you call SendTo().
There is also no need to release to ISocket on suspend, and the INetMgr can be released immediately after GetHostByName and OpenSocket.
Please go back and read my next to last post. That sequence is well tried and is what BREW is expecting from your app.

I don't understand your step 4 in the previous post. What are you trying to achieve by calling Readable() when there is no data expected? You should not call Readable() until after you have used SendTo() and are expecting data back from your server.
Also, since your app is a client, there is no need for step 5 - BREW will implicitly bind to port zero when you call SendTo().
There is also no need to release to ISocket on suspend, and the INetMgr can be released immediately after GetHostByName and OpenSocket.
Please go back and read my next to last post. That sequence is well tried and is what BREW is expecting from your app.

We're going in circles.
Just to prove I'm not totally crazy, I quote from the Knowledge Base on suspend and resume:
"Release Socket connection(s).
If the socket connection(s) are not released, the data call will not be torn down. The associated PPP channel will block the phone from making/receiving voice calls. This is true of current networks, and will change in later generation networks.
Aditionally, please remember to cancel all pending socket operations by calling ISOCKET_Cancel().
For example:
if (pMe->m_piSock) {
ISOCKET_Cancel(pMe->m_piSock,0,0);
ISOCKET_Release(pMe->m_piSock);
pMe->m_piSock = NULL;
}
An exception to this is applications that are designed to run in the background listening on sockets. "
That's why I release the socket on suspend.
I thought we'd established that ISOCKET_Readable did more than just set up the callback. If I don't do it, I'm right back where I started.
Further parsing of the wording of ISOCKET_Bind's documentation indicates that the writeable and retrying the bind is indeed unneccesary.

We're going in circles.
Just to prove I'm not totally crazy, I quote from the Knowledge Base on suspend and resume:
"Release Socket connection(s).
If the socket connection(s) are not released, the data call will not be torn down. The associated PPP channel will block the phone from making/receiving voice calls. This is true of current networks, and will change in later generation networks.
Aditionally, please remember to cancel all pending socket operations by calling ISOCKET_Cancel().
For example:
if (pMe->m_piSock) {
ISOCKET_Cancel(pMe->m_piSock,0,0);
ISOCKET_Release(pMe->m_piSock);
pMe->m_piSock = NULL;
}
An exception to this is applications that are designed to run in the background listening on sockets. "
That's why I release the socket on suspend.
I thought we'd established that ISOCKET_Readable did more than just set up the callback. If I don't do it, I'm right back where I started.
Further parsing of the wording of ISOCKET_Bind's documentation indicates that the writeable and retrying the bind is indeed unneccesary.

The key word from the KB is "connections", i.e. a connected TCP socket. Since you are using UDP, all you need to do is the Cancel(), and you only need to do that if you have registered a callback via Readable().
Please try this sequence, it works for me and others:
Create INetMgr
GetHostByName()
OpenSocket(); you can now release the INetMgr
SendTo(); may need to repeat with Writeable()
RecvFrom(); may need to repeat with Readable()

The key word from the KB is "connections", i.e. a connected TCP socket. Since you are using UDP, all you need to do is the Cancel(), and you only need to do that if you have registered a callback via Readable().
Please try this sequence, it works for me and others:
Create INetMgr
GetHostByName()
OpenSocket(); you can now release the INetMgr
SendTo(); may need to repeat with Writeable()
RecvFrom(); may need to repeat with Readable()

OK, I'll buy that I don't need to release the UDP socket.

OK, I'll buy that I don't need to release the UDP socket.

I have not used UDP sockets (I use TCP so I may be wrong about its usage), but it seems like you are missing something in the basic usage of sockets. There are some examples provided with the BREW toolkit that may help out.
Readable is designed to be called so that the message based architecture of Brew is preserved. Readable gets called when a read returns AEE_NET_WOULDBLOCK. The callback you set then gets called when Brew is next able to read some data.
This process will repeat until all the data is read.
But you should start the reading process with a regular
ISOCKET_Read. That ISOCKET_Read may or may not be able
to read any data immediately. If it is you should process the data,
and if all the data did not come through call ISOCKET_Read again.
And yes you do have to release the socket(s) on a suspend or you will fail TBT.

I have not used UDP sockets (I use TCP so I may be wrong about its usage), but it seems like you are missing something in the basic usage of sockets. There are some examples provided with the BREW toolkit that may help out.
Readable is designed to be called so that the message based architecture of Brew is preserved. Readable gets called when a read returns AEE_NET_WOULDBLOCK. The callback you set then gets called when Brew is next able to read some data.
This process will repeat until all the data is read.
But you should start the reading process with a regular
ISOCKET_Read. That ISOCKET_Read may or may not be able
to read any data immediately. If it is you should process the data,
and if all the data did not come through call ISOCKET_Read again.
And yes you do have to release the socket(s) on a suspend or you will fail TBT.

Your read/readable philosophy is correct, but two details w.r.t. UDP are not:
1) UDP sockets use RecvFrom(), not Read()
2) TBT only verifies that the network goes down when an app is suspended. For UDP sockets, Cancel() is sufficient for this to occur; ISOCKET_Release() is not required.

Your read/readable philosophy is correct, but two details w.r.t. UDP are not:
1) UDP sockets use RecvFrom(), not Read()
2) TBT only verifies that the network goes down when an app is suspended. For UDP sockets, Cancel() is sufficient for this to occur; ISOCKET_Release() is not required.

So I am working on the emulator. IF I write code to bind a UDP socket to a port and just listen, everything is happy. But when I follow the path being discussed in this forum, I continue to get errors, like 531 and 538. The Send works perfectly, but ReceiveFrom always fails.
When I run Qualcomm's example NetDiagnostic, I get the same errors. I was concerned that I might have some problems with my Windows Box, like a Firewall, but I do not have any firewall software on my machine, and I do not have the Firewall stuff from XP SP2 enabled, and I am trying to receive data from a machine on the local network.
Can anyone give me any insight as to why I would be getting these particular errors?

So I am working on the emulator. IF I write code to bind a UDP socket to a port and just listen, everything is happy. But when I follow the path being discussed in this forum, I continue to get errors, like 531 and 538. The Send works perfectly, but ReceiveFrom always fails.
When I run Qualcomm's example NetDiagnostic, I get the same errors. I was concerned that I might have some problems with my Windows Box, like a Firewall, but I do not have any firewall software on my machine, and I do not have the Firewall stuff from XP SP2 enabled, and I am trying to receive data from a machine on the local network.
Can anyone give me any insight as to why I would be getting these particular errors?

Well I made some progress. However, now I can connecting to my own server, and it seems that when I am not recieving anything. When I trace through the code, my ISOCKET_Readable callback gets called twice with AEE_NET_WOULDBLOCK error codes. The second time when I get that wouldblock error code, when I do an ISOCKET_Readable, the callback is never issued again. I tested this with the NetDiagnostic program, and the same seems to hold true there as well.
From the server's standpoint, it is working fine, as the JAVA clients we have connect and communcate without any problems.

Well I made some progress. However, now I can connecting to my own server, and it seems that when I am not recieving anything. When I trace through the code, my ISOCKET_Readable callback gets called twice with AEE_NET_WOULDBLOCK error codes. The second time when I get that wouldblock error code, when I do an ISOCKET_Readable, the callback is never issued again. I tested this with the NetDiagnostic program, and the same seems to hold true there as well.
From the server's standpoint, it is working fine, as the JAVA clients we have connect and communcate without any problems.

sforbes42 wrote:Well I made some progress. However, now I can connecting to my own server, and it seems that when I am not recieving anything. When I trace through the code, my ISOCKET_Readable callback gets called twice with AEE_NET_WOULDBLOCK error codes. The second time when I get that wouldblock error code, when I do an ISOCKET_Readable, the callback is never issued again. I tested this with the NetDiagnostic program, and the same seems to hold true there as well.
From the server's standpoint, it is working fine, as the JAVA clients we have connect and communcate without any problems.
Readable is what you call to be called back when reading is available to
you again. When readable is called you should re-try your read, not call
readable again.

sforbes42 wrote:Well I made some progress. However, now I can connecting to my own server, and it seems that when I am not recieving anything. When I trace through the code, my ISOCKET_Readable callback gets called twice with AEE_NET_WOULDBLOCK error codes. The second time when I get that wouldblock error code, when I do an ISOCKET_Readable, the callback is never issued again. I tested this with the NetDiagnostic program, and the same seems to hold true there as well.
From the server's standpoint, it is working fine, as the JAVA clients we have connect and communcate without any problems.
Readable is what you call to be called back when reading is available to
you again. When readable is called you should re-try your read, not call
readable again.

jmiller2 wrote:Readable is what you call to be called back when reading is available to
you again. When readable is called you should re-try your read, not call
readable again.
I may have misstated what I am doing. I am doing the Read again. When I do a ISOCKET_ReadFrom, I check the error status. If it is a WOULDBLOCK, I make the call to ISOCKET_Readable. When my callback is issued, I call ReadFrom again (Note, I am doing exactly as Qualcomm does in the NetDiagnostics program example in the SDK.). AGain, my ReadFrom gives me a WOULDBLOCK error, so I again, do the ISOCKET_Readable call.
Anyway, I resolved that problem, in that my server, for some reason was ignoring the packets from the BREW client and was never sending an ACK. Once I resolved that issue, my program AND the NetDiagnostic program appear to be receiving something from my server, but both report an error 538 now.
According to the aeeerror.h file, that code is an Invalid Operation (AEE_NET_EINVAL). So, any idea what this means?

jmiller2 wrote:Readable is what you call to be called back when reading is available to
you again. When readable is called you should re-try your read, not call
readable again.
I may have misstated what I am doing. I am doing the Read again. When I do a ISOCKET_ReadFrom, I check the error status. If it is a WOULDBLOCK, I make the call to ISOCKET_Readable. When my callback is issued, I call ReadFrom again (Note, I am doing exactly as Qualcomm does in the NetDiagnostics program example in the SDK.). AGain, my ReadFrom gives me a WOULDBLOCK error, so I again, do the ISOCKET_Readable call.
Anyway, I resolved that problem, in that my server, for some reason was ignoring the packets from the BREW client and was never sending an ACK. Once I resolved that issue, my program AND the NetDiagnostic program appear to be receiving something from my server, but both report an error 538 now.
According to the aeeerror.h file, that code is an Invalid Operation (AEE_NET_EINVAL). So, any idea what this means?

sforbes42 wrote:I may have misstated what I am doing. I am doing the Read again. When I do a ISOCKET_ReadFrom, I check the error status. If it is a WOULDBLOCK, I make the call to ISOCKET_Readable. When my callback is issued, I call ReadFrom again (Note, I am doing exactly as Qualcomm does in the NetDiagnostics program example in the SDK.). AGain, my ReadFrom gives me a WOULDBLOCK error, so I again, do the ISOCKET_Readable call.
Anyway, I resolved that problem, in that my server, for some reason was ignoring the packets from the BREW client and was never sending an ACK. Once I resolved that issue, my program AND the NetDiagnostic program appear to be receiving something from my server, but both report an error 538 now.
According to the aeeerror.h file, that code is an Invalid Operation (AEE_NET_EINVAL). So, any idea what this means?
I don't have it right in front of me, but the
Error docs are slightly confusing in that they add Integer values to
base Hex values. So you might be looking at the wrong error.

sforbes42 wrote:I may have misstated what I am doing. I am doing the Read again. When I do a ISOCKET_ReadFrom, I check the error status. If it is a WOULDBLOCK, I make the call to ISOCKET_Readable. When my callback is issued, I call ReadFrom again (Note, I am doing exactly as Qualcomm does in the NetDiagnostics program example in the SDK.). AGain, my ReadFrom gives me a WOULDBLOCK error, so I again, do the ISOCKET_Readable call.
Anyway, I resolved that problem, in that my server, for some reason was ignoring the packets from the BREW client and was never sending an ACK. Once I resolved that issue, my program AND the NetDiagnostic program appear to be receiving something from my server, but both report an error 538 now.
According to the aeeerror.h file, that code is an Invalid Operation (AEE_NET_EINVAL). So, any idea what this means?
I don't have it right in front of me, but the
Error docs are slightly confusing in that they add Integer values to
base Hex values. So you might be looking at the wrong error.

Yea, that's how I figured out what the error code was.
Fortunately, I finally got my code working. Strange though that the BREW SDK NetDiagnostic example still does not work. Oh well. I'm moving forward again, that's what matters.
Thanks for the feedback.

Yea, that's how I figured out what the error code was.
Fortunately, I finally got my code working. Strange though that the BREW SDK NetDiagnostic example still does not work. Oh well. I'm moving forward again, that's what matters.
Thanks for the feedback.