.NET Components for Mobility

OBEX Bidirectional support?

Last post 01-21-2010 8:28 AM by alanjmcf. 3 replies.
Page 1 of 1 (4 items)
Sort Posts: Previous Next
  • 01-12-2010 12:02 PM

    OBEX Bidirectional support?

    We are using the ObexListener(InTheHand.Net.Persoanl) and BluetoothClient(BrechamObex) classes in the following fashion. We place the server into a Listening state wating for files. We also would like to send responses to the client periodically using BluetoothClient. Files can come into the server at any time so we attempt to always keep the sever in a listening state. We are also trying to permit the server to issue a response at any time to the client (who may be transmitting a file). We are seeing some contention issues in form of failures or hangs. While the sever is in a Listening state we can send responses(files) to the client all day long. Problem occurs while the client is transmitting a file to the server and the server is also attempting to send to the client. Should this work somehow? Not sure how to prohibit the server from sending a file to the client without knowledge of the client's state (is or is not transmitting a file to the server). Am attaching some code based on your sample code and listing where hangs or failures occur. Thank you!

     

    // server code

    // code waiting for files to be received from client, look for HANGS HERE or EXCEPTION HERE

    public int ReceiveFile()
            {

                InTheHand.Net.Bluetooth.BluetoothRadio br = InTheHand.Net.Bluetooth.BluetoothRadio.PrimaryRadio;
                br.Mode = InTheHand.Net.Bluetooth.RadioMode.Discoverable;

                 aTimer = new System.Timers.Timer();
                aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
                // Set the Interval to 1 second.
                aTimer.Interval = 1000;
                aTimer.Enabled = true;

                ol = new ObexListener(ObexTransport.Bluetooth);
                ol.Start();

                t = new System.Threading.Thread(new System.Threading.ThreadStart(DealWithRequest));
                t.Start();

                return 0;
            }

            public void DealWithRequest()
            {
                while (ol.IsListening && (terminateSession == false))
                {
                    //Console.WriteLine("OBEX listening...");
                    System.Diagnostics.Trace.WriteLine("OBEX listening...");
                    try
                    {
                        System.Diagnostics.Trace.WriteLine("LISTENING START");
                        olc = ol.GetContext();
                        olr = olc.Request;
                            // InTheHand.Net.Personal generates an exception and returns null in the
                            // event of a failed session.
                            // If is a general communications failure set pipe back into listening mode

                            System.Diagnostics.Trace.WriteLine("LISTENING STOP");
                            string filename = Uri.UnescapeDataString(olr.RawUrl.TrimStart(new char[ { '/' }));
                            BluetoothClient btc = new BluetoothClient();
                            BluetoothEndPoint bep = (BluetoothEndPoint)olr.RemoteEndPoint;
                            String vmw_name = btc.GetRemoteMachineName(bep.Address);
                            System.Diagnostics.Trace.WriteLine("New file " + filename + " received from: " + vmw_name + " BT Address: " + bep.Address);
                            String ofile = VMwPath + "\\" + vmw_name + "-" + DateTime.Now.ToString("yyMMddHHmmss") + "-" + filename;
                            olr.WriteFile(ofile);
                            System.Diagnostics.Trace.WriteLine("file saved to: {0}" + ofile);
                    }

                    catch (Exception ex)
                    {
                        System.Diagnostics.Trace.WriteLine("OBEX Listener exception: " + ex);
                        continue; // keep is listening state even in event of failed file transfer

                    }
                }
            }

     

     // server code sending responses to client

            public unsafe int SendFile(byte * device, byte * filename, uint deviceLength, uint fileLength)
            {
                    //----------------------------------------------------------
                    // Network Connect
                    //----------------------------------------------------------

                    byte[ b = new byte[deviceLength];
                    for (int i = 0; i < deviceLength; i++)
                    {
                        bIdea = deviceIdea;
                    }
                    givenDeviceName = System.Text.ASCIIEncoding.ASCII.GetString(b);

                    byte[ c = new byte[fileLength];
                    for (int i = 0; i < fileLength; i++)
                    {
                        cIdea = filenameIdea;
                    }
                    curPath = System.Text.ASCIIEncoding.ASCII.GetString(c);

                    btCli = new BluetoothClient();
                    System.Diagnostics.Trace.WriteLine("Searching for Bluetooth device with name: " + givenDeviceName);
                    // only search for paired and remebered devices, do not search for new devices
                    BluetoothDeviceInfo[ devices = btCli.DiscoverDevices(20, true, true, false);

                    BluetoothAddress addr = null;
                    foreach (BluetoothDeviceInfo curDevice in devices)
                    {
                        if (curDevice.DeviceName.Equals(givenDeviceName))
                        {
                            addr = curDevice.DeviceAddress;
                        }
                    }
                    if (addr == null)
                    {
                        System.Diagnostics.Trace.WriteLine("No Bluetooth device with the given name was found.");
                        return;
                    }
                    BluetoothEndPoint ep = new BluetoothEndPoint(addr,
                        InTheHand.Net.Bluetooth.BluetoothService.ObexObjectPush);
                    try
                    {

                        btCli.Connect(ep); // OFTEN EXCEPTION HERE, file must have come in from client
                        peerStream = btCli.GetStream();

                        //----------------------------------------------------------
                        // OBEX Connect & Send(s)
                        //----------------------------------------------------------

                        ObexClientSession sess = new ObexClientSession(peerStream, UInt16.MaxValue);
                        ObexHeaderCollection headers = new ObexHeaderCollection();
                        // The number of files we're gonna send = 1.
                        headers.Add(ObexHeaderId.Count, 1);

                        sess.Connect(headers); // OFTEN HANGS HERE, assume file has come in from client

                        //----------------------------------------------------------
                        // OBEX Send file
                        //----------------------------------------------------------

                        PutFile(sess, curPath);
                        sess.Disconnect();

                    }
                    catch (Exception ex)
                    {

                        System.Diagnostics.Trace.WriteLine("SendFile failed: " + ex);

                    }
                    if (peerStream != null) peerStream.Close();
                    if (btCli != null) btCli.Close();

    }

            static void PutFile(ObexClientSession sess, String filepath)
            {
                using (FileStream src = File.OpenRead(filepath))
                {
                    long lengthInBits = src.Length * 8;
                    String name = Path.GetFileName(filepath);

                    System.Diagnostics.Trace.WriteLine("Filename: {0}" + filepath);
                    System.Diagnostics.Trace.WriteLine("  Length = {0}" + src.Length);

                    DateTime start = DateTime.UtcNow;

                    sess.PutFrom(src, name, null, src.Length);
                    TimeSpan ts = DateTime.UtcNow - start;
                    double bps = ((lengthInBits / ts.TotalMilliseconds) * 1000);
                    System.Diagnostics.Trace.WriteLine("  PutFrom took {0}, at an average {1} bps." + ts + bps);
                }
            }

    We also often see a hang in SocketStreamIOAdapters.cpp. We are sending a file(response) to the client and then a file begins to be received from the client where we are in a listening state.

            //
            public override int Receive(byte[ buffer, int size, SocketFlags socketFlags)
            {
                return Receive(buffer, 0, size, socketFlags); // HANGS HERE

            }

    Am running with latest changest 63059 which includes the hangs fixes for events in which the client or server is shutdown or experiences a severe error during a transmission from the client to the server. The client is a Linux device running Bluez stack. ussp-push is used to send files to the server while opd is running in the background on the client to receive responses. Not seeing any issues on client.

    Thank you!

     

    Ed Ruffing
    Software Engineer
  • 01-18-2010 1:56 PM In reply to

    Re: OBEX Bidirectional support?

    Hmm.  I wish my Bluetooth low-level protocol knowledge was good enought to give good information to this type of question. :-(  I wish I could find a good book on it.  I wonder also whether different dongles (and stacks)have much different capabilities...

    I thought that one case have been ok however.  The Widcomm docs include this text: "When the first client connects with the server, the Bluetooth stack automatically puts the server into slave mode. In slave mode the server can not respond to service discovery requests from other clients. So, the server must call SwitchRole() to restore the server to Bluetooth master mode. The existing connection is not disturbed; but the server can now accept additional connections."  That would tend to suggest that A->B and then B->A should be ok if neither device did a mode change...

    Or, I wondered whether there may be no capacity in the client->server direction with the PUT data being transferred, but surely the packets from the two RFCOMM connections should be treated equally.

     

    BTW All the problems with ObexListener reading incorrectly from the connection have been fixed.  So hopefully any problems (not that I hope *any* problems occur) are due to hangs due to no data being transferred rather that the infinite loops which were prossible previous if the connection closed early.

    Alan J. McFarlane
    http://www.alanjmcf.me.uk/
    Please follow-up in the newsgroup for the benefit of all.
    Have I helped? Consider visiting my Amazon wishlist, see my homepage.
  • 01-19-2010 2:19 PM In reply to

    Re: OBEX Bidirectional support?

    The Put code resides in Brecham.Obex.ClientSession which imagine resides in Brecham.Obex.dll and do see some hangs there. Is the Brecham.Obex.dll code open source also? Could not find a repository on the site where IntheHand.Net.Personal.dll code resides. Am running with changeset 63172. Was considering dropping the server out of listening mode when the server wishes to send a response to the client but could result in missing some incoming data. Am assuming we should be able to do a receive and put in two seperate threads but sounds like the low level code could potentially vary and have issues with this. Perhaps supporting transfers in only one direction at a time would give more stability? Will keep investigating.

    ObexClientSession sess = new ObexClientSession(peerStream, UInt16.MaxValue);
                        ObexHeaderCollection headers = new ObexHeaderCollection();
                        // The number of files we're gonna send = 1.
                        headers.Add(ObexHeaderId.Count, 1);

    sess.Connect(headers); // OFTEN HANGS HERE, assume file has come in from client

     Thank you!

     

    Ed Ruffing
    Software Engineer
  • 01-21-2010 8:28 AM In reply to

    Re: OBEX Bidirectional support?

    Bah I posted an response to this but the site crashed! :-(

    I presume that it sitting in a stream.Read waiting for data to arrive.  Break into it in the debugger and the call stack should show where it's sitting. Andy has done has done a very high quality implementation, I guess the more that 700 unit-tests help, and I've think there have only been one or two minor bugs, so I doubt that it is hanging for any other reason.  (Hopefully we're in the state now and will exit if the connection is close.  I've added some unit-tests covering the OBEX classes)

     

    On the other question. I *wonder* if there're any limitiations imposed by particular dongles, maybe high-end ones support multiple (RFCOMM) connections better??

    Or I suppose you could try and use just the one (RFCOMM) connection.  Would it be timely enough for the client to a special GET request for status after (and before) a PUT operation?  Andy's open-source Brecham.Obex Server can handle GET requests.

    Alan J. McFarlane
    http://www.alanjmcf.me.uk/
    Please follow-up in the newsgroup for the benefit of all.
    Have I helped? Consider visiting my Amazon wishlist, see my homepage.
Page 1 of 1 (4 items)
Copyright © 2001-2010 In The Hand Ltd. All rights reserved. Terms of Use and Privacy Policy.