Watt-32 tcp/ip  2.2 dev-rel.10
sock_io.c
Go to the documentation of this file.
1 
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 
11 #include "copyrigh.h"
12 #include "wattcp.h"
13 #include "strings.h"
14 #include "misc.h"
15 #include "pcconfig.h"
16 #include "pctcp.h"
17 
18 /*
19  * sock_putc - put a character
20  * - no expansion but flushes on CR/LF
21  * - returns character
22  */
23 BYTE W32_CALL sock_putc (sock_type *s, BYTE c)
24 {
25 #if !defined(USE_UDP_ONLY)
26  if (c == '\n' || c == '\r')
27  sock_flushnext (s);
28 #endif
29  sock_write (s, &c, 1);
30  return (c);
31 }
32 
33 
34 /*
35  * sock_puts - does not append carriage return in binary mode
36  * - returns length.
37  * - only accepts ASCII strings.
38  */
39 int W32_CALL sock_puts (sock_type *s, const BYTE *data)
40 {
41  int len;
42 
43 #if defined(USE_BSD_API)
44  if (s->raw.ip_type == IP4_TYPE)
45  return (0); /* not supported yet */
46 #endif
47 
48  len = strlen ((const char*)data);
49 
50  if (!(s->tcp.sockmode & SOCK_MODE_BINARY)) /* udp/tcp ASCII mode */
51  {
52  BYTE tmp [MAX_IP4_DATA];
54  if (len > 0) /* merge in a newline */
55  {
56  len = min (len, SIZEOF(tmp)-2); /* May truncate, tough luck */
57  memcpy (&tmp, data, len);
58  tmp [len++] = '\r';
59  tmp [len++] = '\n';
60  data = tmp;
61  }
62  else
63  {
64  data = (const BYTE*) "\r\n";
65  len = 2;
66  }
67  len = sock_write (s, data, len);
68  }
69  else
70  {
71 #if !defined(USE_UDP_ONLY)
72  sock_flushnext (s);
73 #endif
74  len = sock_write (s, data, len);
75  }
76  return (len);
77 }
78 
79 
80 /*
81  * sock_gets - read a {\r|\n} terminated string from a UDP/TCP socket.
82  * - return length of returned string
83  * - removes end of line terminator(s)
84  * - Quentin Smart and Mark Phillips fixed some problems
85  *
86  * BIG WARNING: Don't use sock_gets() for packetised protocols like
87  * SSH. Only suitable for ASCII orientented protocols
88  * like POP3/SMTP/NNTP etc.
89  */
90 WORD W32_CALL sock_gets (sock_type *s, BYTE *data, int bmax)
91 {
92  int len = 0, frag = 0;
93  BYTE *nl_p, *cr_p, eol;
94 
95 #if defined(USE_BSD_API)
96  if (s->raw.ip_type == IP4_TYPE)
97  return (0); /* raw sockets not supported */
98 #endif
99 
100 #if !defined(USE_UDP_ONLY)
101  if (s->udp.ip_type == TCP_PROTO &&
102  s->tcp.missed_seq[0] != s->tcp.missed_seq[1])
103  frag = s->tcp.missed_seq[1] - s->tcp.recv_next;
104 #endif
105 
106  if (s->tcp.sockmode & SOCK_MODE_SAWCR)
107  {
108  s->tcp.sockmode &= ~SOCK_MODE_SAWCR;
109  if (s->tcp.rx_datalen > 0 &&
110  (*s->tcp.rx_data == '\n' || *s->tcp.rx_data == '\0'))
111  {
112  memmove (s->tcp.rx_data, s->tcp.rx_data + 1, frag + s->tcp.rx_datalen);
113  s->tcp.rx_datalen--;
114  }
115  }
116 
117  /* Return if there is nothing in the buffer.
118  */
119  if (s->tcp.rx_datalen == 0)
120  return (0);
121 
122  /* If there is space for all the data, then copy all of it,
123  * otherwise, only copy what the space will allow (taking
124  * care to reserve space for the null terminator.
125  */
126  --bmax;
127  if (bmax > s->tcp.rx_datalen)
128  bmax = s->tcp.rx_datalen;
129  memcpy (data, s->tcp.rx_data, bmax);
130  data [bmax] = '\0';
131 
132  /* At this point, data is a null-terminated string,
133  * containing as much of the data as is possible.
134  */
135  len = bmax;
136 
137  /* Because we are in ASCII mode, we assume that the
138  * sender will be consistent in which kind of CRLF is
139  * sent (e.g. one and only one of \r\n, \r0, \r, or \n).
140  * So if both \r and \n are found, we assume that they
141  * are always next to each other, and \n\r is invalid.
142  */
143 
144  /* Zero the first occurance of \r and \n in data.
145  */
146  cr_p = (BYTE*) memchr (data, '\r', bmax);
147  if (cr_p)
148  *cr_p = '\0';
149 
150  nl_p = (BYTE*) memchr (data, '\n', bmax);
151  if (nl_p)
152  *nl_p = '\0';
153 
154 #if !defined(USE_UDP_ONLY)
155  /*
156  * Handle flushed end of strings EE 02.02.28
157  */
158  if (s->tcp.ip_type == TCP_PROTO)
159  {
160  if ((s->tcp.locflags & LF_GOT_PUSH) && !cr_p)
161  {
162  cr_p = data + bmax;
163  s->tcp.locflags &= ~LF_GOT_PUSH;
164  }
165 
166  /* Return if we did not find '\r' or '\n' yet, but still had room,
167  * *and* the connection can get more data!
168  */
169  if (!cr_p && !nl_p &&
170  (bmax > s->tcp.rx_datalen) &&
171  ((UINT)s->tcp.rx_datalen < s->tcp.max_rx_data) &&
172  (s->tcp.state != tcp_StateLASTACK) &&
173  (s->tcp.state != tcp_StateCLOSED))
174  {
175  *data = '\0';
176  return (0);
177  }
178  }
179 #endif
180 
181  /* If we did find a terminator, then stop there.
182  */
183  if (cr_p || nl_p)
184  {
185  /* Find the length of the first line of data in 'data'.
186  */
187  len = (int) (nl_p == NULL ? (char*)cr_p - (char*)data :
188  cr_p == NULL ? (char*)nl_p - (char*)data :
189  nl_p < cr_p ? (char*)nl_p - (char*)data :
190  (char*)cr_p - (char*)data);
191 
192  /* We found a terminator character ...
193  */
194  bmax = len + 1;
195 
196  /* If '\r' at end of data, might get a '\0' or '\n' in next packet
197  */
198  if (cr_p && s->tcp.rx_datalen == bmax)
199  s->tcp.sockmode |= SOCK_MODE_SAWCR;
200 
201  /* ... and it could have been "\r\0" or "\r\n".
202  */
203  eol = s->tcp.rx_data [bmax];
204  if ((s->tcp.rx_datalen > bmax) &&
205  (eol == '\0' || (cr_p && eol == '\n')))
206  bmax++;
207  }
208 
209  /* Remove the first line from the buffer.
210  */
211  s->tcp.rx_datalen -= bmax;
212  if (frag || s->tcp.rx_datalen > 0)
213  memmove (s->tcp.rx_data, s->tcp.rx_data + bmax, frag + s->tcp.rx_datalen);
214 
215 #if !defined(USE_UDP_ONLY)
216  /*
217  * Update window if less than MSS/2 free in receive buffer
218  */
219  if (s->tcp.ip_type == TCP_PROTO &&
220  s->tcp.state != tcp_StateCLOSED &&
221  (s->tcp.max_rx_data - s->tcp.rx_datalen) < s->tcp.max_seg/2)
222  TCP_SENDSOON (&s->tcp);
223 #endif
224 
225  return (len);
226 }
227 
228 /*
229  * Return a single character.
230  * Returns EOF on fail (no data or connection closed).
231  */
232 int W32_CALL sock_getc (sock_type *s)
233 {
234  BYTE ch = 0;
235  return (sock_read (s, &ch, 1) < 1 ? EOF : ch);
236 }
237 
246 WORD W32_CALL sock_dataready (sock_type *s)
247 {
248  char *p;
249  int len = s->tcp.rx_datalen;
250 
251 #if defined(USE_BSD_API)
252  if (s->raw.ip_type == IP4_TYPE)
253  return (0); /* not supported yet */
254 #endif
255 
256  if (len && !(s->tcp.sockmode & SOCK_MODE_BINARY)) /* ASCII mode */
257  {
258  p = (char*)s->tcp.rx_data;
259 
260  if (s->tcp.sockmode & SOCK_MODE_SAWCR) /* !! S. Lawson */
261  {
262  s->tcp.sockmode &= ~SOCK_MODE_SAWCR;
263  if (*p == '\n' || *p == '\0')
264  {
265  s->tcp.rx_datalen = --len;
266  memmove (p, p+1, s->tcp.rx_datalen);
267  if (!len)
268  return (0);
269  }
270  }
271 
272  if ((UINT)len == s->tcp.max_rx_data)
273  return (len);
274 
275  if (s->tcp.ip_type == TCP_PROTO) /* GV 99.12.02 */
276  {
277  if (s->tcp.state == tcp_StateLASTACK) /* EE 99.07.02 */
278  return (len);
279 
280  /* S. Lawson - happens if final ACK arrives before app reads data
281  */
282  if (s->tcp.state == tcp_StateCLOSED)
283  return (len);
284  }
285 
286  /* check for terminating `\r' and/or `\n'
287  */
288  if (memchr(p, '\r', len))
289  return (len);
290  if (memchr(p, '\n', len)) /* EE added 99/04/30 */
291  return (len);
292  return (0);
293  }
294  return (len);
295 }
296 
297 #ifdef NOT_YET
298 
301 int W32_CALL sock_putcw (sock_type *s, wchar_t ch)
302 {
303 }
304 
308 int W32_CALL sock_putsw (sock_type *s, const wchar_t *data)
309 {
310 }
311 
315 int W32_CALL sock_getsw (sock_type *s, wchar_t *data, int n)
316 {
317 }
318 
322 wchar_t W32_CALL sock_getcw (sock_type *s)
323 {
324 }
325 #endif
326 
wchar_t W32_CALL sock_getcw(sock_type *s)
Definition: sock_io.c:322
int W32_CALL sock_read(sock_type *s, BYTE *buf, size_t maxlen)
Read a socket with maximum 'maxlen' bytes.
Definition: pctcp.c:2875
WORD ip_type
same ofs as for udp/tcp Socket
Definition: wattcp.h:695
int W32_CALL sock_puts(sock_type *s, const BYTE *data)
Definition: sock_io.c:39
int W32_CALL sock_putcw(sock_type *s, wchar_t ch)
Definition: sock_io.c:301
Core definitions.
int W32_CALL sock_write(sock_type *s, const BYTE *data, int len)
Writes data and returns length written.
Definition: pctcp.c:2960
int W32_CALL sock_putsw(sock_type *s, const wchar_t *data)
Definition: sock_io.c:308
DWORD missed_seq[2]
S.
Definition: wattcp.h:665
int W32_CALL sock_getsw(sock_type *s, wchar_t *data, int n)
Definition: sock_io.c:315
void W32_CALL sock_flushnext(sock_type *s)
Causes next transmission to have a flush (PUSH bit set).
Definition: pctcp.c:3124
UINT max_seg
MSS for this connection.
Definition: wattcp.h:658
WORD W32_CALL sock_dataready(sock_type *s)
sock_dataready - returns number of bytes waiting to be read.
Definition: sock_io.c:246
DWORD recv_next
SEQ number we expect to receive.
Definition: wattcp.h:623
UINT state
tcp connection state
Definition: wattcp.h:622