6 #include <sys/select.h>
9 /* Ways of finding the hardware MAC on this machine... */
10 /* This is the Linux only fallback. */
11 @@ -130,20 +131,18 @@ namespace NSLU2Upgrade {
12 * non-static (real) Handler.
14 void Handler(const struct pcap_pkthdr *packet_header, const u_char *packet) {
15 - /* This should only be called once... */
17 - throw std::logic_error("Handler called twice");
19 /* Verify the protocol and originating address of the packet, then
24 if (packet_header->caplen > 14 && (broadcast ||
25 std::memcmp(packet+6, header, 6) == 0)) {
26 - /* Record the address and copy the data */
27 - std::memcpy(source, packet+6, 6);
28 const size_t len(packet_header->caplen - 14);
29 if (len > captureSize)
30 - throw std::logic_error("packet too long");
32 + /* Record the address and copy the data */
33 + std::memcpy(source, packet+6, 6);
34 std::memcpy(captureBuffer, packet+14, len);
37 @@ -156,7 +155,7 @@ namespace NSLU2Upgrade {
38 * packet and the buffer should be big enough.
40 if (packet_header->caplen < packet_header->len)
41 - throw std::logic_error("truncated packet");
44 /*IGNORE EVIL: known evil cast */
45 reinterpret_cast<PCapWire*>(user)->Handler(packet_header, packet);
46 @@ -173,56 +172,24 @@ namespace NSLU2Upgrade {
47 virtual void Receive(void *buffer, size_t &size, unsigned long timeout) {
48 /* Now try to read packets until the timeout has been consumed.
50 - struct timeval tvStart;
51 - if (timeout > 0 && gettimeofday(&tvStart, 0) != 0)
52 - throw OSError(errno, "gettimeofday(base)");
55 captureBuffer = buffer;
58 + time_count = timeout / 2000; /* 2 ms intervals */
61 /*IGNORE EVIL: known evil cast */
62 - int count(pcap_dispatch(pcap, 1, PCapHandler,
63 - reinterpret_cast<u_char*>(this)));
64 + int count = pcap_dispatch(pcap, 1, PCapHandler,
65 + reinterpret_cast<u_char*>(this));
68 - /* Were any packets handled? */
73 - /* else try again. */
74 - } else if (count == 0) {
75 - /* Nothing to handle - do the timeout, do this
76 - * by waiting a bit then trying again, the trick
77 - * to this is to work out how long to wait each
78 - * time, for the moment a 10ms delay is used.
83 - struct timeval tvNow;
84 - if (gettimeofday(&tvNow, 0) != 0)
85 - throw OSError(errno, "gettimeofday(now)");
87 - unsigned long t(tvNow.tv_sec - tvStart.tv_sec);
90 - t -= tvStart.tv_usec;
95 - tvNow.tv_usec = timeout-t;
96 - if (tvNow.tv_usec > 10000)
97 - tvNow.tv_usec = 10000;
99 - /* Delay, may be interrupted - this should
100 - * be portable to the BSDs (since the
101 - * technique originates in BSD.)
103 - (void)select(0, 0, 0, 0, &tvNow);
105 + /* Were any packets handled? */
107 + size = captureSize;
111 /* Error condition. */
114 @@ -232,7 +199,8 @@ namespace NSLU2Upgrade {
116 throw std::logic_error("pcap unexpected result");
118 - } while (timeout != 0);
120 + } while (time_count > 0);
122 /* Here on timeout. */
124 @@ -288,6 +256,7 @@ NSLU2Upgrade::Wire *NSLU2Upgrade::Wire::
125 const unsigned char *mac, const unsigned char *address, int uid) {
126 /* This is used to store the error passed to throw. */
127 static char PCapErrbuf[PCAP_ERRBUF_SIZE];
128 + struct bpf_program fp;
130 /* Check the device name. If not given use 'DEFAULT_ETHERNET_IF'. */
132 @@ -301,20 +270,12 @@ NSLU2Upgrade::Wire *NSLU2Upgrade::Wire::
133 * for other ethernet MACs. (Because the code above does not
134 * check that the destination matches the device in use).
136 - pcap = pcap_open_live(device, 1540, false/*promiscuous*/, 1/*ms*/, PCapErrbuf);
137 + pcap = pcap_open_live(device, 1540, false/*promiscuous*/, 2/*ms*/, PCapErrbuf);
140 throw WireError(errno, PCapErrbuf);
143 - /* Always do a non-blocking read, because the 'timeout' above
144 - * doesn't work on Linux (return is immediate) and on OSX (and
145 - * maybe other BSDs) the interface tends to hang waiting for
146 - * the timeout to expire even after receiving a single packet.
148 - if (pcap_setnonblock(pcap, true, PCapErrbuf))
149 - throw WireError(errno, PCapErrbuf);
152 /* The MAC of the transmitting device is needed - without
153 * this the return packet won't go to the right place!