Watt-32 tcp/ip  2.2 dev-rel.10
pcrecv.c
Go to the documentation of this file.
1 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <limits.h>
9 
10 #include "wattcp.h"
11 #include "strings.h"
12 #include "language.h"
13 #include "bsddbug.h"
14 #include "misc.h"
15 #include "pcsed.h"
16 #include "pcbuf.h"
17 #include "pctcp.h"
18 #include "pcrecv.h"
19 
20 #define RECV_USED 0xF7E3D2B1L
21 #define RECV_UNUSED 0xE6D2C1AFL
22 
23 /* UDP "sequence number" for finding the oldest packet.
24  * Newest received has higher 'p->buf_seqnum' number
25  */
26 static long seq_num = 0;
27 
28 /*
29  * Gets upcalled when data arrives.
30  * We MUST set 'p->buf_len = -1' to signal a 0-byte UDP packet
31  * not 0
32  */
33 static int W32_CALL sock_recvdaemon (
34  sock_type *s, const void *data, unsigned len,
35  const tcp_PseudoHeader *ph, const udp_Header *udp)
36 {
37  recv_data *r;
38  recv_buf *p;
39  unsigned i;
40 
41  switch (s->udp.ip_type)
42  {
43  case UDP_PROTO:
44  r = (recv_data*) s->udp.rx_data;
45  p = (recv_buf*) r->recv_bufs;
46  if (r->recv_sig != RECV_USED)
47  {
48  outsnl (_LANG("ERROR: udp recv data conflict"));
49  return (0);
50  }
51  /* find an unused buffer
52  */
53  for (i = 0; i < r->recv_bufnum; i++, p++)
54  switch (p->buf_sig)
55  {
56  case RECV_USED:
57  break;
58  case RECV_UNUSED: /* take this one */
59  p->buf_sig = RECV_USED;
60  p->buf_hisport = udp->srcPort;
61  p->buf_seqnum = seq_num++;
62 #if defined(USE_IPV6)
63  if (s->udp.is_ip6)
64  memcpy (&p->buf_hisip6, &((tcp_PseudoHeader6*)ph)->src,
65  sizeof(p->buf_hisip6));
66 
67  else
68 #endif
69  p->buf_hisip = ph->src;
70  len = min (len, sizeof(p->buf_data));
71  if (len > 0)
72  {
73  memcpy (p->buf_data, data, len);
74  p->buf_len = (short) len;
75  }
76  else
77  p->buf_len = -1; /* a 0-byte probe */
78 #if 0
79  SOCK_DEBUGF (("\nsock_recvdaemon(): buffer %d, "
80  "seq-num %ld, len %d",
81  i, seq_num-1, p->buf_len));
82 #endif
83  return (0);
84  default:
85  outsnl (_LANG("ERROR: sock_recv_daemon data err"));
86  return (0);
87  }
88  return (0);
89 
90 #if !defined(USE_UDP_ONLY)
91  case TCP_PROTO:
92  {
93  _tcp_Socket *t = &s->tcp;
94 
95  r = (recv_data*) t->rx_data;
96 
97  if (r->recv_sig != RECV_USED)
98  {
99  outsnl (_LANG("ERROR: tcp recv data conflict"));
100  return (0);
101  }
102  /* stick it on the end if you can
103  */
104  i = t->max_rx_data - t->rx_datalen;
105  if (i > 1)
106  {
107  /* we can accept some of this */
108  if (len > i)
109  len = i;
110  if (len > 0)
111  memcpy (r->recv_bufs + t->rx_datalen, data, len);
112  t->rx_datalen += len;
113  return (len);
114  }
115  return (0); /* didn't take none */
116  }
117 #endif
118  }
119  return (0);
120 }
121 
122 
123 int W32_CALL sock_recv_used (const sock_type *s)
124 {
125  const recv_data *r;
126  const recv_buf *p;
127 
128  int i, len;
129 
130  switch (_chk_socket(s))
131  {
132  case VALID_UDP:
133  r = (const recv_data*) s->udp.rx_data;
134  p = (const recv_buf*) r->recv_bufs;
135  if (r->recv_sig != RECV_USED)
136  return (-1);
137 
138  for (i = len = 0; i < r->recv_bufnum; i++, p++)
139  if (p->buf_sig == RECV_USED)
140  len += abs (p->buf_len); /* -1 -> 1 */
141  return (len);
142 
143 #if !defined(USE_UDP_ONLY)
144  case VALID_TCP:
145  r = (const recv_data*) s->tcp.rx_data;
146  if (r->recv_sig != RECV_USED)
147  return (-1);
148  return (s->tcp.rx_datalen);
149 #endif
150  }
151  return (0);
152 }
153 
154 
155 int W32_CALL sock_recv_init (sock_type *s, void *space, unsigned len)
156 {
157  recv_buf *p = (recv_buf*) space;
158  recv_data *r = (recv_data*) s->udp.rx_data;
159  int i;
160 
161  WATT_ASSERT ((DWORD)len <= USHRT_MAX);
162  memset (r, 0, s->udp.max_rx_data); /* clear Rx-buffer */
163  memset (p, 0, len); /* clear data area */
164 
165  s->udp.protoHandler = (ProtoHandler)sock_recvdaemon;
166  r->recv_sig = RECV_USED;
167  r->recv_bufs = (BYTE*) p;
168  r->recv_bufnum = (WORD) (len / sizeof(recv_buf));
169 
170  if (s->udp.ip_type == UDP_PROTO)
171  for (i = 0; i < r->recv_bufnum; i++, p++)
172  p->buf_sig = RECV_UNUSED;
173  return (0);
174 }
175 
176 int W32_CALL sock_recv_from (sock_type *s, DWORD *hisip, WORD *hisport,
177  void *buffer, unsigned len, int peek)
178 {
179 #if !defined(USE_UDP_ONLY)
180  _tcp_Socket *t;
181 #endif
182  recv_buf *p, *oldest = NULL;
183  recv_data *r = (recv_data*) s->udp.rx_data;
184  long seqnum = LONG_MAX;
185  int i;
186 
187  if (r->recv_sig != RECV_USED)
188  {
189  SOCK_ERRNO (EBADF);
190 
191  /* To differentiate an error from 0-byte probe (also -1) */
192  return (-1);
193  }
194 
195  switch (s->udp.ip_type)
196  {
197  case UDP_PROTO:
198  p = (recv_buf*) r->recv_bufs;
199 
200  /* find the oldest used UDP buffer.
201  */
202  for (i = 0; i < r->recv_bufnum; i++, p++)
203  {
204  switch (p->buf_sig)
205  {
206  case RECV_UNUSED:
207  break;
208 
209  case RECV_USED:
210 #if defined(__MSDOS__)
211  /* Drop looped packets sent by us (running
212  * under Win32 DOS box using NDIS3PKT or SwsVpkt).
213  */
214  if ((_eth_ndis3pkt || _eth_SwsVpkt) &&
215  !s->tcp.is_ip6 && p->buf_hisip == intel(my_ip_addr))
216  {
217  p->buf_sig = RECV_UNUSED;
218  continue;
219  }
220 #endif
221  if (p->buf_seqnum < seqnum) /* ignore wraps */
222  {
223  seqnum = p->buf_seqnum;
224  oldest = p;
225 #if 0
226  SOCK_DEBUGF (("\nsock_recv_from(): buffer %d, "
227  "seq-num %ld, len %d",
228  i, seqnum, p->buf_len));
229 #endif
230  }
231  break;
232 
233  default:
234  outsnl (_LANG("ERROR: sock_recv_init data err"));
235  return (0);
236  }
237  }
238  break;
239 
240 #if !defined(USE_UDP_ONLY)
241  case TCP_PROTO:
242  t = &s->tcp;
243  len = min (len, (unsigned)t->rx_datalen);
244  if (len)
245  memcpy (buffer, r->recv_bufs, len);
246  return (len);
247 #endif
248  }
249 
250  if (!oldest)
251  return (0);
252 
253  /* found the oldest UDP packet */
254 
255  p = oldest;
256  if (p->buf_len < 0) /* a 0-byte probe packet */
257  len = -1;
258  else
259  {
260  len = min ((unsigned)p->buf_len, len);
261  memcpy (buffer, p->buf_data, len);
262  }
263 
264 #if defined(USE_IPV6)
265  if (s->tcp.is_ip6)
266  {
267  if (hisip)
268  memcpy (hisip, &p->buf_hisip6, sizeof(ip6_address));
269  }
270  else
271 #endif
272  if (hisip)
273  *hisip = p->buf_hisip;
274 
275  if (hisport)
276  *hisport = p->buf_hisport;
277 
278  if (!peek)
279  p->buf_sig = RECV_UNUSED;
280  return (len);
281 }
282 
283 int W32_CALL sock_recv (sock_type *s, void *buffer, unsigned len)
284 {
285  return sock_recv_from (s, NULL, NULL, buffer, len, 0);
286 }
287 
BOOL _eth_ndis3pkt
for DOS-programs only
Definition: pcsed.c:57
Core definitions.
BOOL _eth_SwsVpkt
for DOS and Win32 programs
Definition: pcsed.c:58
DWORD my_ip_addr
our IP address
Definition: pctcp.c:70