Menu

Two questions regarding recvfile.

Help
2008-03-03
2013-04-25
  • Cristian Orellana

    Hi,

    with the new version of the API there's so much new things :D.

    I've an application (let's call it A) that is constantly sending status data to an ObexServer (let's call it B), the problem is I haven't found a way to get (on B) the name of the files that A is sending, my current solution is using the date to name the incoming files.

    After looking at the code I found this on _obex.py

    " def newrequest(self, opcode, reqheaders, nonheaderdata, hasbody):
            #print "-> newrequest", opcode, reqheaders, nonheaderdata, hasbody
            #print "-> incoming file name:", reqheaders.get(0x01)
            self.__busy = True

            if opcode == _lightblueobex.PUT:
                return (_lightblueobex.SUCCESS, {}, self.__fileobject)
            elif opcode in (_lightblueobex.CONNECT, _lightblueobex.DISCONNECT):
                return (_lightblueobex.SUCCESS, {}, None)
            else:
                return (_lightblueobex.NOT_IMPLEMENTED, {}, None)"

    But I'm not sure how to use it, or if it really works in my case.

    That's one situation, the other is the following:
    I'll have to add another sender (similar to A) so I will need to identify on B wich client is sending the data. Is there any way to do this? Checking the code I found the following commented code on _obex.py (line 367)

    "    try:
            conn, addr = sock.accept()
            # print "A client connected:", addr
            server = OBEXObjectPushServer(conn.fileno(), fileobj)
            server.run()
            conn.close()"

    where the client is being identified, is there any problem if I return that value on recvfile()??

    Thanks a lot, any tip is appreciated.

     
    • blam

      blam - 2008-03-04

      Hi,

      > I've an application (let's call it A) that is constantly sending status data to an ObexServer (let's call it B), the problem is I haven't found
      > a way to get (on B) the name of the files that A is sending, my current solution is using the date to name the incoming files.

      If you include the filename when sending the file from OBEXClient (e.g. client.put({"name": "file.txt"}, fileobject) ) the OBEX server will be able to receive the filename. What are you doing to run the OBEX server?

      > After looking at the code I found this on _obex.py
      >
      >" def newrequest(self, opcode, reqheaders, nonheaderdata, hasbody):

      This is part of the code for the OBEX Push server that runs when recvfile() is called. You can use this to run your OBEX Push server (on 'B') if you like - just lift the code from recvfile() and you won't have to deal with the limitations of recvfile() (only receiving one file per client, can't check the filename or client bluetooth address, etc.).

      > I'll have to add another sender (similar to A) so I will need to identify on B wich client is sending the data. Is there any way to do
      > this? Checking the code I found the following commented code on _obex.py (line 367)
      > [...]
      > where the client is being identified, is there any problem if I return that value on recvfile()??

      Not at all. I'd like to return that from recvfile(), really, but I haven't done the code to implement it cross-platform (takes a lot more code on Series 60).

       
    • blam

      blam - 2008-03-04

      Ah, wait, I see what you're saying. I thought you were talking about using sendfile() on A but you're actually talking about using recvfile() on B. And you want to get the filename and the client address when you run recvfile() on B.

      Yes, it's all in the code you mentioned. So just modify _obex.py like this:

      1) In newrequest(), add something like this:

              self.__incomingfilename = reqheaders.get(_lightblueobex.NAME)   # _lightblueobex.NAME == 0x01

      2) At the end of the run() method, add

               return self.__incomingfilename

      3) In recvfile(), substitue

               server.run()

      with

              filename = server.run()

      And then at the end of recvfile() do

              return (addr, filename)

      And now you should be able to get something like:
              >>> lightblue.obex.recvfile()
              ("aa:bb:cc:dd:ee:ff", "receivedfile.txt")

      You can get a lot of other request information from inside newrequest() - e.g. the size or type of the incoming file by using _lightblueobex.LENGTH or _lightblueobex.TYPE instead. Check lightblueobex_main.c for the defined constants.

       
    • Cristian Orellana

      Thanks a lot for the fast reply!

      I did the changes but it seems there is a problem on the 0.3.1 release, in the recvfile function, before including the changes to get the filename and client address I installed the "clean" 0.3.1 sources and the example to receive a file didn't worked.

      Is lightblue working ok with the last version of pybluez? I made a clean install of ubuntu 7.1 and unfortunately the problem persists.

      In _obex.py there is a function called newrequest, after uncommenting the two prints I get this when running the recvfile example:

      -> newrequest 0 {} � False

      (yeah, mainly garbage)

      The lines I uncommented are this:

          def newrequest(self, opcode, reqheaders, nonheaderdata, hasbody):
              print "-> newrequest", opcode, reqheaders, nonheaderdata, hasbody
              print "-> incoming file name:", reqheaders.get(0x01)

      What is wrong?

       
      • blam

        blam - 2008-03-07

        So recvfile() doesn't return and just keeps waiting? If it's just printing that single "newrequest" line, it looks like the OBEX server is only receiving a CONNECT request and doesn't get a PUT request. Can you run hcidump -X -V and post what you get when you call recvfile()?

        I don't think the problem involves pybluez.

        What device are you sending the file from? And did this work for you with lightblue 0.2.3?

         
    • Cristian Orellana

      Hi,

      recvfile() closes prematurely, I get the address of the client correctly, it also prints the "-> got file!" message (at run() function, line ~285) on _obex.py. It seems the server never get the OBEX_EV_STREAMAVAIL event so obexserver_streamavailable() is never called (this is just a guess).

      The log for hcidump is here: http://www.pastey.net/83485-31l3 as you can see there is a Put request (also the filename, type and date are provided)

      There is a curious response code just after that:

      252    < ACL data: handle 1 flags 0x02 dlen 11
      253        L2CAP(d): cid 0x0040 len 7 [psm 3]
      254          RFCOMM(d): UIH: cr 0 dlci 2 pf 0 ilen 3 fcs 0x40
      255            OBEX: Put rsp(f): status 501 len 3

      Why status 501? (not implemented)

      The device I'm doing this tests is a Nokia 6103 and a Nokia 5200.

      Well I hope this information helps, once again, thanks for the support.

      Cristian.

       
      • blam

        blam - 2008-03-10

        D'oh - it looks like it's failing because LightBlue isn't setting the response code for the openobex handle when an OBEX_EV_REQHINT is received.

        Can you please confirm this is the problem by trying this fix? Just add this line to the end of obexserver_incomingrequest() in lightblueobex_server.c:
           
            OBEX_ObjectSetRsp(obj, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS);

        And then the server should not respond 'Not implemented' anymore.

         
        • Cristian Orellana

          Thanks!

          it worked!

           
          • blam

            blam - 2008-03-11

            Great, I'll fix it for the next release. Thanks for reporting the bug, I appreciate it.

             
    • Cristian Orellana

      :D

      Right now I'm able to store the incoming file with the original filename, but a new problem arises.

      When a second client wants to connect to the server and send a file to it, it seems the request is queued, because only after the current connection ends, then new put request starts.

      I've tried to fix this via threads, but the same behavior continues, maybe because the implementation of the OBEXObjectPushServer and run() blocks all with the "while True:"

      I know this may not be a lightblue-related question but, is there any way for the server to attend 2 or more clients and the same time? (I know 7 is the cap for each interface).

       
    • Cristian Orellana

      Nevermind the last post, I've managed to solve the problem... except for one little detail.

      is stopadvertise(sock) supposed to delete the record entry at the sdp server? if so, the function isn't doing it.

      Here's how to reproduce the scenario:

      run the example for recvfile:

      import lightblue
      #from lightblue import * -- throws an error!
      s = socket()
      s.bind(("", 0))
      advertise("My OBEX Service", s, OBEX)
      obex.recvfile(s, "MyFile.txt")

      -- Now check for rechandles at sdp server: (in other terminal)

      sdptool get 10000

      Service Name: Receptor
      Service RecHandle: 0x10000
      Service Class ID List:
        "OBEX Object Push" (0x1105)
      Protocol Descriptor List:
        "L2CAP" (0x0100)
        "RFCOMM" (0x0003)
          Channel: 3
        "OBEX" (0x0008)
      Profile Descriptor List:
        "OBEX Object Push" (0x1105)
          Version: 0x0100

      now perform a stopadvertise()

      lightblue.stopadvertise(s)

      now check the sdp server again:

      sdptool get 10000

      Service Name: Receptor
      Service RecHandle: 0x10000
      Service Class ID List:
        "OBEX Object Push" (0x1105)
      Protocol Descriptor List:
        "L2CAP" (0x0100)
        "RFCOMM" (0x0003)
          Channel: 3
        "OBEX" (0x0008)
      Profile Descriptor List:
        "OBEX Object Push" (0x1105)
          Version: 0x0100

      The record persists!

      That cause all the requests made to the ObexObjectPushServer are canalized to the same socket, not allowing a parallelized treatment of clients.
      What I'm doing now is just delete the records manually and calling stopadvertise anyways. doing this I can serve up to 7 clients at the same time.

      Cristian.

       
      • blam

        blam - 2008-03-15

        I've checked this and it does work for me - the SDP record is removed correctly. Maybe upgrading to the latest pybluez or bluez libraries and see if that helps.

        Also, you could try using the select module to run an asynchronous OBEX server.

         

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.