OpenWrt – Blame information for rev 2
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | --- a/pcap_wire.cc |
2 | +++ b/pcap_wire.cc |
||
3 | @@ -18,6 +18,7 @@ |
||
4 | |||
5 | #include <sys/time.h> |
||
6 | #include <sys/select.h> |
||
7 | +#include <sys/poll.h> |
||
8 | |||
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. |
||
13 | */ |
||
14 | void Handler(const struct pcap_pkthdr *packet_header, const u_char *packet) { |
||
15 | - /* This should only be called once... */ |
||
16 | - if (captured) |
||
17 | - throw std::logic_error("Handler called twice"); |
||
18 | - |
||
19 | /* Verify the protocol and originating address of the packet, then |
||
20 | * return this packet. |
||
21 | */ |
||
22 | + if (captured) |
||
23 | + return; |
||
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"); |
||
31 | + return; |
||
32 | + /* Record the address and copy the data */ |
||
33 | + std::memcpy(source, packet+6, 6); |
||
34 | std::memcpy(captureBuffer, packet+14, len); |
||
35 | captureSize = len; |
||
36 | captured = true; |
||
37 | @@ -156,7 +155,7 @@ namespace NSLU2Upgrade { |
||
38 | * packet and the buffer should be big enough. |
||
39 | */ |
||
40 | if (packet_header->caplen < packet_header->len) |
||
41 | - throw std::logic_error("truncated packet"); |
||
42 | + return; |
||
43 | |||
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. |
||
49 | */ |
||
50 | - struct timeval tvStart; |
||
51 | - if (timeout > 0 && gettimeofday(&tvStart, 0) != 0) |
||
52 | - throw OSError(errno, "gettimeofday(base)"); |
||
53 | + int time_count; |
||
54 | |||
55 | captureBuffer = buffer; |
||
56 | captureSize = size; |
||
57 | captured = false; |
||
58 | + time_count = timeout / 2000; /* 2 ms intervals */ |
||
59 | + time_count++; |
||
60 | do { |
||
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)); |
||
66 | |||
67 | - if (count > 0) { |
||
68 | - /* Were any packets handled? */ |
||
69 | - if (captured) { |
||
70 | - size = captureSize; |
||
71 | - return; |
||
72 | - } |
||
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. |
||
79 | - */ |
||
80 | - if (timeout == 0) |
||
81 | - break; |
||
82 | - |
||
83 | - struct timeval tvNow; |
||
84 | - if (gettimeofday(&tvNow, 0) != 0) |
||
85 | - throw OSError(errno, "gettimeofday(now)"); |
||
86 | - |
||
87 | - unsigned long t(tvNow.tv_sec - tvStart.tv_sec); |
||
88 | - t *= 1000000; |
||
89 | - t += tvNow.tv_usec; |
||
90 | - t -= tvStart.tv_usec; |
||
91 | - if (t > timeout) |
||
92 | - break; |
||
93 | - |
||
94 | - tvNow.tv_sec = 0; |
||
95 | - tvNow.tv_usec = timeout-t; |
||
96 | - if (tvNow.tv_usec > 10000) |
||
97 | - tvNow.tv_usec = 10000; |
||
98 | - |
||
99 | - /* Delay, may be interrupted - this should |
||
100 | - * be portable to the BSDs (since the |
||
101 | - * technique originates in BSD.) |
||
102 | - */ |
||
103 | - (void)select(0, 0, 0, 0, &tvNow); |
||
104 | - } else { |
||
105 | + /* Were any packets handled? */ |
||
106 | + if (captured) { |
||
107 | + size = captureSize; |
||
108 | + return; |
||
109 | + } |
||
110 | + if (count < 0) { |
||
111 | /* Error condition. */ |
||
112 | if (count == -1) { |
||
113 | if (errno != EINTR) |
||
114 | @@ -232,7 +199,8 @@ namespace NSLU2Upgrade { |
||
115 | } else |
||
116 | throw std::logic_error("pcap unexpected result"); |
||
117 | } |
||
118 | - } while (timeout != 0); |
||
119 | + time_count--; |
||
120 | + } while (time_count > 0); |
||
121 | |||
122 | /* Here on timeout. */ |
||
123 | size = 0; |
||
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; |
||
129 | |||
130 | /* Check the device name. If not given use 'DEFAULT_ETHERNET_IF'. */ |
||
131 | if (device == NULL) |
||
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). |
||
135 | */ |
||
136 | - pcap = pcap_open_live(device, 1540, false/*promiscuous*/, 1/*ms*/, PCapErrbuf); |
||
137 | + pcap = pcap_open_live(device, 1540, false/*promiscuous*/, 2/*ms*/, PCapErrbuf); |
||
138 | |||
139 | if (pcap == NULL) |
||
140 | throw WireError(errno, PCapErrbuf); |
||
141 | } |
||
142 | |||
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. |
||
147 | - */ |
||
148 | - if (pcap_setnonblock(pcap, true, PCapErrbuf)) |
||
149 | - throw WireError(errno, PCapErrbuf); |
||
150 | - |
||
151 | try { |
||
152 | /* The MAC of the transmitting device is needed - without |
||
153 | * this the return packet won't go to the right place! |