Merge lp:~andrefcruz/nfcpy/npp-1.0 into lp:nfcpy

Proposed by André Cruz
Status: Merged
Merged at revision: 78
Proposed branch: lp:~andrefcruz/nfcpy/npp-1.0
Merge into: lp:nfcpy
Diff against target: 103 lines (+23/-13)
1 file modified
nfc/npp/server.py (+23/-13)
To merge this branch: bzr merge lp:~andrefcruz/nfcpy/npp-1.0
Reviewer Review Type Date Requested Status
Stephen Tiedemann Approve
Review via email: mp+64703@code.launchpad.net

Description of the change

I implemented the ability for the NPP server to run in single-threaded mode and be stopped by the return of the process() method.

In my scenario this is useful because I only want to receive a message, process it, and continue the program without the NPP server (the Android API only allows the phone to send 1 message per LLCP link establishment).

If you find this useful then merge...

To post a comment you must log in.
lp:~andrefcruz/nfcpy/npp-1.0 updated
75. By André Cruz

Support python 2.6.

Revision history for this message
Stephen Tiedemann (stephen-tiedemann) wrote :

Andre, I wouldn't mind to make the NPP server single-threaded/single-connection *onyly*. As implemented in Android, it is always *one* system client that opens *one* connection to send NDEF data, An NPP server should actually never need to handle more than one connection at a time (in practice not even during the same session). And I don't think there will be much evolution of the NPP specification; I rather dare to predict a forthcoming Android release will support the NFC Forum way of getting NDEF across LLCP.

lp:~andrefcruz/nfcpy/npp-1.0 updated
76. By André Cruz

Make single-threaded the default behavior.

Revision history for this message
André Cruz (andrefcruz) wrote :

I agree, I made "single-thread" the default behavior. I didn't remove the multi-threaded code since someone may still find a use for it, if they decide to use the NPP protocol using only nfcpy and not Android devices.

Revision history for this message
Stephen Tiedemann (stephen-tiedemann) wrote :

Merged to trunk with a few modifications:
- parameter in __init__ renamed 'threaded'
- set listen socket backlog to 0 for non-threaded operation
- rejected server termination by return value from process()
- added option for example npp server to terminate after receipt of one ndef message

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'nfc/npp/server.py'
--- nfc/npp/server.py 2011-06-15 08:40:42 +0000
+++ nfc/npp/server.py 2011-06-23 13:55:11 +0000
@@ -12,10 +12,11 @@
12import nfc.llcp12import nfc.llcp
1313
14class NPPServer(Thread):14class NPPServer(Thread):
15 """ Simple NPP server15 """ Simple NPP server. If single_threaded is True then a new thread will not be spawned.
16 """16 """
17 def __init__(self):17 def __init__(self, single_threaded=True):
18 super(NPPServer, self).__init__()18 super(NPPServer, self).__init__()
19 self.single_threaded = single_threaded
1920
20 def run(self):21 def run(self):
21 socket = nfc.llcp.socket(nfc.llcp.DATA_LINK_CONNECTION)22 socket = nfc.llcp.socket(nfc.llcp.DATA_LINK_CONNECTION)
@@ -27,9 +28,15 @@
27 nfc.llcp.listen(socket, backlog=2)28 nfc.llcp.listen(socket, backlog=2)
28 while True:29 while True:
29 client_socket = nfc.llcp.accept(socket)30 client_socket = nfc.llcp.accept(socket)
30 client_thread = Thread(target=NPPServer.serve,31 if self.single_threaded:
32 log.debug("got client in single_threaded mode")
33 if NPPServer.serve(client_socket, self):
34 break
35 else:
36 log.debug("got client, will spawn thread")
37 client_thread = Thread(target=NPPServer.serve,
31 args=[client_socket, self])38 args=[client_socket, self])
32 client_thread.start()39 client_thread.start()
33 except nfc.llcp.Error as e:40 except nfc.llcp.Error as e:
34 log.error(str(e))41 log.error(str(e))
35 finally:42 finally:
@@ -45,20 +52,20 @@
45 if data is None:52 if data is None:
46 log.debug("connection closed, no data")53 log.debug("connection closed, no data")
47 return54 return
48 55
49 while nfc.llcp.poll(socket, "recv"):56 while nfc.llcp.poll(socket, "recv"):
50 data += nfc.llcp.recv(socket)57 data += nfc.llcp.recv(socket)
5158
52 log.debug("got {:d} octets data".format(len(data)))59 log.debug("got {0:d} octets data".format(len(data)))
53 if len(data) < 10:60 if len(data) < 10:
54 log.debug("npp msg initial fragment too short")61 log.debug("npp msg initial fragment too short")
55 return # bail out, this is a bad client62 return # bail out, this is a bad client
5663
57 version, num_entries = unpack(">BI", data[:5])64 version, num_entries = unpack(">BI", data[:5])
58 log.debug("version {:d}, {:d} entries"65 log.debug("version {0:d}, {1:d} entries"
59 .format(version, num_entries))66 .format(version, num_entries))
60 if (version >> 4) > 1:67 if (version >> 4) > 1:
61 log.debug("unsupported version {:d}".format(version>>4))68 log.debug("unsupported version {0:d}".format(version>>4))
62 return69 return
6370
64 if num_entries != 1:71 if num_entries != 1:
@@ -67,13 +74,13 @@
6774
68 remaining = data[5:]75 remaining = data[5:]
69 for i in range(num_entries):76 for i in range(num_entries):
70 log.debug("processing NDEF message #{:d}".format(i+1))77 log.debug("processing NDEF message #{0:d}".format(i+1))
71 if len(remaining) < 5:78 if len(remaining) < 5:
72 log.debug("insufficient data for action code and ndef size")79 log.debug("insufficient data for action code and ndef size")
73 return80 return
7481
75 action_code, length = unpack(">BI", remaining[:5])82 action_code, length = unpack(">BI", remaining[:5])
76 log.debug("action code {:d}, ndef length {:d}"83 log.debug("action code {0:d}, ndef length {1:d}"
77 .format(action_code, length))84 .format(action_code, length))
7885
79 if action_code != 1:86 if action_code != 1:
@@ -87,12 +94,14 @@
8794
88 # message complete, now handle the request95 # message complete, now handle the request
89 ndef_message_data = remaining[:length]96 ndef_message_data = remaining[:length]
90 log.debug("have complete ndef message, {:d} octets"97 log.debug("have complete ndef message, {0:d} octets"
91 .format(len(ndef_message_data)))98 .format(len(ndef_message_data)))
92 npp_server.process(ndef_message_data)99 if npp_server.process(ndef_message_data) and npp_server.single_threaded:
100 return True
93101
94 # prepare for next102 # prepare for next
95 remaining = remaining[length:]103 remaining = remaining[length:]
104 return
96105
97 except nfc.llcp.Error as e:106 except nfc.llcp.Error as e:
98 log.debug("caught exception {0}".format(e))107 log.debug("caught exception {0}".format(e))
@@ -105,7 +114,8 @@
105 def process(self, ndef_message_data):114 def process(self, ndef_message_data):
106 """Processes NDEF messages. This method should be overwritten by a115 """Processes NDEF messages. This method should be overwritten by a
107 subclass of NPPServer to customize it's behavior. The default116 subclass of NPPServer to customize it's behavior. The default
108 implementation prints each record.117 implementation prints each record. If NPP server is single threaded
118 and this method returns True, the server stops processing.
109 """119 """
110 log.debug("ndef push server process message")120 log.debug("ndef push server process message")
111 log.debug(ndef_message_data.encode("hex"))121 log.debug(ndef_message_data.encode("hex"))

Subscribers

People subscribed via source and target branches