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
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.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
> 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).
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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:
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.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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:
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?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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:
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).
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
-- 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.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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.
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).
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.
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?
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?
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.
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.
Thanks!
it worked!
Great, I'll fix it for the next release. Thanks for reporting the bug, I appreciate it.
: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).
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.
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.