1 /* $Id$
2 *
3 * XPilot, a multiplayer gravity war game. Copyright (C) 1991-95 by
4 *
5 * Bjørn Stabell (bjoerns@staff.cs.uit.no)
6 * Ken Ronny Schouten (kenrsc@stud.cs.uit.no)
7 * Bert G sbers (bert@mc.bio.uva.nl)
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #ifdef WIN32
25
26 # include <winsock.h>
27 /* Hack - my errno doesn't include EWOULDBLOCK * - GP */
28 #ifndef DUMB_WIN
29 # define EWOULDBLOCK WSAEWOULDBLOCK
30 /* this next one redefines va_start and va_end, but it is necessary -GP*/
31 #ifndef _WINDOWS
32 # include <varargs.h>
33 #endif
34 #endif
35 #else
36 # include <unistd.h>
37 # include <stdlib.h>
38 # include <stdio.h>
39 # include <errno.h>
40 # include <sys/types.h>
41 # if defined(__hpux)
42 # include <time.h>
43 # else
44 # include <sys/time.h>
45 # endif
46 # ifdef __sgi
47 # include <bstring.h>
48 # endif
49 #endif
50
51 /* MinGW doesn't have EWOULDBLOCK either - mikaelh */
52 #ifdef MINGW
53 #define EWOULDBLOCK WSAEWOULDBLOCK
54 #endif
55
56
57 #include "angband.h"
58 #include "version.h"
59 #include "const.h"
60 /*#include "error.h"*/
61 #include "sockbuf.h"
62 #include "pack.h"
63 #include "bit.h"
64
65 #ifdef MSDOS
66 #include "net-ibm.h"
67 #else
68 # ifdef WIN32
69 # include "net-win.h"
70 # else
71 # include "net-unix.h"
72 # endif /* WIN32 */
73 #endif /* MSDOS */
74
75 char net_version[] = VERSION;
76
Sockbuf_init(sockbuf_t * sbuf,int sock,int size,int state)77 int Sockbuf_init(sockbuf_t *sbuf, int sock, int size, int state)
78 {
79 if ((sbuf->buf = sbuf->ptr = (char *) malloc(size)) == NULL) {
80 return -1;
81 }
82 sbuf->sock = sock;
83 sbuf->state = state;
84 sbuf->len = 0;
85 sbuf->size = size;
86 sbuf->ptr = sbuf->buf;
87 sbuf->state = state;
88 return 0;
89 }
90
Sockbuf_cleanup(sockbuf_t * sbuf)91 int Sockbuf_cleanup(sockbuf_t *sbuf)
92 {
93 if (sbuf->buf != NULL) {
94 free(sbuf->buf);
95 }
96 sbuf->buf = sbuf->ptr = NULL;
97 sbuf->size = sbuf->len = 0;
98 sbuf->state = 0;
99 return 0;
100 }
101
Sockbuf_clear(sockbuf_t * sbuf)102 int Sockbuf_clear(sockbuf_t *sbuf)
103 {
104 sbuf->len = 0;
105 sbuf->ptr = sbuf->buf;
106 return 0;
107 }
108
Sockbuf_advance(sockbuf_t * sbuf,int len)109 int Sockbuf_advance(sockbuf_t *sbuf, int len)
110 {
111 /*
112 * First do a few buffer consistency checks.
113 */
114 if (sbuf->ptr > sbuf->buf + sbuf->len) {
115 errno = 0;
116 plog("Sockbuf pointer too far");
117 sbuf->ptr = sbuf->buf + sbuf->len;
118 }
119 if (sbuf->ptr < sbuf->buf) {
120 errno = 0;
121 plog("Sockbuf pointer bad");
122 sbuf->ptr = sbuf->buf;
123 }
124 if (sbuf->len > sbuf->size) {
125 errno = 0;
126 plog("Sockbuf len too far");
127 sbuf->len = sbuf->size;
128 }
129 if (sbuf->len < 0) {
130 errno = 0;
131 plog("Sockbuf len bad");
132 sbuf->len = 0;
133 }
134 if (len <= 0) {
135 if (len < 0) {
136 errno = 0;
137 plog(format("Sockbuf advance negative (%d)", len));
138 }
139 }
140 else if (len >= sbuf->len) {
141 if (len > sbuf->len) {
142 errno = 0;
143 plog("Sockbuf advancing too far");
144 }
145 sbuf->len = 0;
146 sbuf->ptr = sbuf->buf;
147 } else {
148 #if defined(__hpux) || defined(VMS) || defined(__apollo) || defined(SVR4) || defined(_SEQUENT_) || defined(SYSV) || !defined(bcopy)
149 memmove(sbuf->buf, sbuf->buf + len, sbuf->len - len);
150 #else
151 bcopy(sbuf->buf + len, sbuf->buf, sbuf->len - len);
152 #endif
153 sbuf->len -= len;
154 if (sbuf->ptr - sbuf->buf <= len) {
155 sbuf->ptr = sbuf->buf;
156 } else {
157 sbuf->ptr -= len;
158 }
159 }
160 return 0;
161 }
162
Sockbuf_rollback(sockbuf_t * sbuf,int len)163 int Sockbuf_rollback(sockbuf_t *sbuf, int len)
164 {
165 /*
166 * First do a few buffer consistency checks.
167 */
168 if (sbuf->ptr < sbuf->buf) {
169 errno = 0;
170 plog("Sockbuf pointer bad");
171 sbuf->ptr = sbuf->buf;
172 }
173 if (len > sbuf->ptr - sbuf->buf) {
174 plog("Sockbuf rollback too big");
175 len = sbuf->ptr - sbuf->buf;
176 }
177 if (len < 0) {
178 errno = 0;
179 plog(format("Sockbuf rollback negative (%d)", len));
180 }
181 else {
182 sbuf->ptr -= len;
183 }
184 return 0;
185 }
186
Sockbuf_flush(sockbuf_t * sbuf)187 int Sockbuf_flush(sockbuf_t *sbuf)
188 {
189 int len,
190 i;
191
192 if (BIT(sbuf->state, SOCKBUF_WRITE) == 0) {
193 errno = 0;
194 plog("No flush on non-writable socket buffer");
195 plog(format("(state=%02x,buf=%08x,ptr=%08x,size=%d,len=%d,sock=%d)",
196 sbuf->state, sbuf->buf, sbuf->ptr, sbuf->size, sbuf->len,
197 sbuf->sock));
198 return -1;
199 }
200 if (BIT(sbuf->state, SOCKBUF_LOCK) != 0) {
201 errno = 0;
202 plog(format("No flush on locked socket buffer (0x%02x)", sbuf->state));
203 return -1;
204 }
205 if (sbuf->len <= 0) {
206 if (sbuf->len < 0) {
207 errno = 0;
208 plog("Write socket buffer length negative");
209 sbuf->len = 0;
210 sbuf->ptr = sbuf->buf;
211 }
212 return 0;
213 }
214
215 #if 0
216 /* maintain a few statistics */
217 {
218 static int max = 1024, avg, count;
219
220 avg += sbuf->len;
221 count++;
222 if (sbuf->len > max) {
223 max = sbuf->len;
224 printf("Max packet = %d, avg = %d\n", max, avg / count);
225 }
226 else if (max > 1024 && (count & 0x03) == 0) {
227 max--;
228 }
229 }
230 #endif
231
232 if (BIT(sbuf->state, SOCKBUF_DGRAM) != 0) {
233 errno = 0;
234 i = 0;
235 #if 0
236 if (rand() % 12 == 0) /* artificial packet loss */
237 len = sbuf->len;
238 else
239 #endif
240 while ((len = DgramWrite(sbuf->sock, sbuf->buf, sbuf->len)) <= 0) {
241 if (len == 0
242 || errno == EWOULDBLOCK
243 || errno == EAGAIN) {
244 Sockbuf_clear(sbuf);
245 return 0;
246 }
247 if (errno == EINTR) {
248 errno = 0;
249 continue;
250 }
251 #if 0
252 if (errno == ECONNREFUSED) {
253 plog("Send refused");
254 Sockbuf_clear(sbuf);
255 return -1;
256 }
257 #endif
258 if (++i > MAX_SOCKBUF_RETRIES) {
259 plog(format("Can't send on socket (%d,%d)", sbuf->sock, sbuf->len));
260 Sockbuf_clear(sbuf);
261 return -1;
262 }
263 { static int send_err;
264 if ((send_err++ & 0x3F) == 0) {
265 /*plog(format("send (%d)", i));*/
266 }
267 }
268 if (GetSocketError(sbuf->sock) == -1) {
269 plog("GetSocketError send");
270 return -1;
271 }
272 errno = 0;
273 }
274 if (len != sbuf->len) {
275 errno = 0;
276 plog(format("Can't write complete datagram (%d,%d)", len, sbuf->len));
277 }
278 Sockbuf_clear(sbuf);
279 } else {
280 errno = 0;
281 while ((len = DgramWrite(sbuf->sock, sbuf->buf, sbuf->len)) <= 0) {
282 if (errno == EINTR) {
283 errno = 0;
284 continue;
285 }
286 if (errno != EWOULDBLOCK
287 && errno != EAGAIN) {
288 plog("Can't write on socket");
289 return -1;
290 }
291 return 0;
292 }
293 Sockbuf_advance(sbuf, len);
294 }
295 return len;
296 }
297
Sockbuf_write(sockbuf_t * sbuf,char * buf,int len)298 int Sockbuf_write(sockbuf_t *sbuf, char *buf, int len)
299 {
300 if (BIT(sbuf->state, SOCKBUF_WRITE) == 0) {
301 errno = 0;
302 plog("No write to non-writable socket buffer");
303 return -1;
304 }
305 if (sbuf->size - sbuf->len < len) {
306 if (BIT(sbuf->state, SOCKBUF_LOCK | SOCKBUF_DGRAM) != 0) {
307 errno = 0;
308 plog(format("No write to locked socket buffer (%d,%d,%d,%d)",
309 sbuf->state, sbuf->size, sbuf->len, len));
310 return -1;
311 }
312 if (Sockbuf_flush(sbuf) == -1) {
313 return -1;
314 }
315 if (sbuf->size - sbuf->len < len) {
316 return 0;
317 }
318 }
319 memcpy(sbuf->buf + sbuf->len, buf, len);
320 sbuf->len += len;
321
322 return len;
323 }
324
Sockbuf_read(sockbuf_t * sbuf)325 int Sockbuf_read(sockbuf_t *sbuf)
326 {
327 int max,
328 i,
329 len;
330
331 if (BIT(sbuf->state, SOCKBUF_READ) == 0) {
332 errno = 0;
333 plog(format("No read from non-readable socket buffer (%d)", sbuf->state));
334 return -1;
335 }
336 if (BIT(sbuf->state, SOCKBUF_LOCK) != 0) {
337 return 0;
338 }
339 if (sbuf->ptr > sbuf->buf) {
340 Sockbuf_advance(sbuf, sbuf->ptr - sbuf->buf);
341 }
342 if ((max = sbuf->size - sbuf->len) <= 0) {
343 static int before;
344 if (before++ == 0) {
345 errno = 0;
346 plog(format("Read socket buffer not big enough (%d,%d)",
347 sbuf->size, sbuf->len));
348 }
349 return -1;
350 }
351 if (BIT(sbuf->state, SOCKBUF_DGRAM) != 0) {
352 errno = 0;
353 i = 0;
354 #if 0
355 if (rand() % 12 == 0) /* artificial packet loss */
356 len = sbuf->len;
357 else
358 #endif
359 while ((len = DgramRead(sbuf->sock, sbuf->buf + sbuf->len, max)) <= 0) {
360 if (len == 0) {
361 return 0;
362 }
363 if (errno == EINTR) {
364 errno = 0;
365 continue;
366 }
367 if (errno == EWOULDBLOCK
368 || errno == EAGAIN) {
369 return 0;
370 }
371 #if 0
372 if (errno == ECONNREFUSED) {
373 plog("Receive refused");
374 return -1;
375 }
376 #endif
377 if (++i > MAX_SOCKBUF_RETRIES) {
378 plog("Can't recv on socket");
379 return -1;
380 }
381 { static int recv_err;
382 if ((recv_err++ & 0x3F) == 0) {
383 /*plog(format("recv (%d)", i));*/
384 }
385 }
386 if (GetSocketError(sbuf->sock) == -1) {
387 plog("GetSocketError recv");
388 return -1;
389 }
390 errno = 0;
391 }
392 sbuf->len += len;
393 } else {
394 errno = 0;
395 while ((len = DgramRead(sbuf->sock, sbuf->buf + sbuf->len, max)) <= 0) {
396 if (len == 0) {
397 return 0;
398 }
399 if (errno == EINTR) {
400 errno = 0;
401 continue;
402 }
403 if (errno != EWOULDBLOCK
404 && errno != EAGAIN) {
405 plog("Can't read on socket");
406 return -1;
407 }
408 return 0;
409 }
410 sbuf->len += len;
411 }
412
413 return sbuf->len;
414 }
415
Sockbuf_copy(sockbuf_t * dest,sockbuf_t * src,int len)416 int Sockbuf_copy(sockbuf_t *dest, sockbuf_t *src, int len)
417 {
418 if (len < dest->size - dest->len) {
419 errno = 0;
420 plog("Not enough room in destination copy socket buffer");
421 return -1;
422 }
423 if (len < src->len) {
424 errno = 0;
425 plog("Not enough data in source copy socket buffer");
426 return -1;
427 }
428 memcpy(dest->buf + dest->len, src->buf, len);
429 dest->len += len;
430
431 return len;
432 }
433
434 #if STDVA
Packet_printf(sockbuf_t * sbuf,char * fmt,...)435 int Packet_printf(sockbuf_t *sbuf, char *fmt, ...)
436 #else
437 int Packet_printf(va_alist)
438 va_dcl
439 #endif
440 {
441 #define PRINTF_FMT 1
442 #define PRINTF_IO 2
443 #define PRINTF_SIZE 3
444
445 int i,
446 cval,
447 ival,
448 count,
449 failure = 0,
450 max_str_size;
451 unsigned uval;
452 short int sval;
453 unsigned short int usval;
454 long int lval;
455 unsigned long int ulval;
456 char *str,
457 *end,
458 *buf;
459 va_list ap;
460 #if !STDVA
461 char *fmt;
462 sockbuf_t *sbuf;
463
464 va_start(ap);
465 sbuf = va_arg(ap, sockbuf_t *);
466 fmt = va_arg(ap, char *);
467 #else
468 va_start(ap, fmt);
469 #endif
470
471 /*
472 * Stream socket buffers should flush the buffer if running
473 * out of write space. This is currently not needed cause
474 * only datagram sockets are used or the buffer is locked.
475 */
476
477 /*
478 * Mark the end of the available buffer space.
479 */
480 end = sbuf->buf + sbuf->size;
481
482 buf = sbuf->buf + sbuf->len;
483
484 for (i = 0; failure == 0 && fmt[i] != '\0'; i++) {
485 if (fmt[i] == '%') {
486 switch (fmt[++i]) {
487 case 'c':
488 if (buf + 1 >= end) {
489 failure = PRINTF_SIZE;
490 break;
491 }
492 cval = va_arg(ap, int);
493 *buf++ = cval;
494 break;
495 case 'd':
496 if (buf + 4 >= end) {
497 failure = PRINTF_SIZE;
498 break;
499 }
500 ival = va_arg(ap, int);
501 *buf++ = ival >> 24;
502 *buf++ = ival >> 16;
503 *buf++ = ival >> 8;
504 *buf++ = ival;
505 break;
506 case 'u':
507 if (buf + 4 >= end) {
508 failure = PRINTF_SIZE;
509 break;
510 }
511 uval = va_arg(ap, unsigned);
512 *buf++ = uval >> 24;
513 *buf++ = uval >> 16;
514 *buf++ = uval >> 8;
515 *buf++ = uval;
516 break;
517 case 'h':
518 if (buf + 2 >= end) {
519 failure = PRINTF_SIZE;
520 break;
521 }
522 switch (fmt[++i]) {
523 case 'd':
524 sval = va_arg(ap, int);
525 *buf++ = sval >> 8;
526 *buf++ = sval;
527 break;
528 case 'u':
529 usval = va_arg(ap, unsigned);
530 *buf++ = usval >> 8;
531 *buf++ = usval;
532 break;
533 default:
534 failure = PRINTF_FMT;
535 break;
536 }
537 break;
538 case 'l':
539 if (buf + 4 >= end) {
540 failure = PRINTF_SIZE;
541 break;
542 }
543 switch (fmt[++i]) {
544 case 'd':
545 lval = va_arg(ap, long int);
546 *buf++ = lval >> 24;
547 *buf++ = lval >> 16;
548 *buf++ = lval >> 8;
549 *buf++ = lval;
550 break;
551 case 'u':
552 ulval = va_arg(ap, unsigned long int);
553 *buf++ = ulval >> 24;
554 *buf++ = ulval >> 16;
555 *buf++ = ulval >> 8;
556 *buf++ = ulval;
557 break;
558 default:
559 failure = PRINTF_FMT;
560 break;
561 }
562 break;
563 case 'S': /* Big strings */
564 case 'I': /* Semi-big strings: Item name (including inscription) */
565 case 's': /* Small strings */
566 max_str_size = (fmt[i] == 'S') ? MSG_LEN : ((fmt[i] == 'I') ? ONAME_LEN : MAX_CHARS);
567 str = va_arg(ap, char *);
568 #if 1
569 char *stop;
570 if (buf + max_str_size >= end) {
571 stop = end;
572 } else {
573 stop = buf + max_str_size;
574 }
575 /* Send the nul byte too */
576 do {
577 if (buf >= stop) {
578 break;
579 }
580 } while ((*buf++ = *str++) != '\0');
581 if (buf > stop) {
582 failure = PRINTF_SIZE;
583 }
584 #else
585 /* Optimized version - mikaelh */
586 long len = strlen(str) + 1;
587
588 if (len > max_str_size) {
589 len = max_str_size;
590 }
591
592 if (buf + len > end) {
593 failure = PRINTF_SIZE;
594 } else {
595 memcpy(buf, str, len);
596 buf += len;
597 }
598 #endif
599 break;
600 default:
601 failure = PRINTF_FMT;
602 break;
603 }
604 } else {
605 failure = PRINTF_FMT;
606 }
607 }
608 if (failure != 0) {
609 count = -1;
610 if (failure == PRINTF_SIZE) {
611 #if 0
612 static int before;
613 if ((before++ & 0x0F) == 0) {
614 printf("Write socket buffer not big enough (%d,%d,\"%s\")\n",
615 sbuf->size, sbuf->len, fmt);
616 }
617 #endif
618 if (BIT(sbuf->state, SOCKBUF_DGRAM) != 0) {
619 count = 0;
620 failure = 0;
621 }
622 }
623 else if (failure == PRINTF_FMT) {
624 errno = 0;
625 plog(format("Error in format string (\"%s\")", fmt));
626 }
627 } else {
628 count = buf - (sbuf->buf + sbuf->len);
629 sbuf->len += count;
630 }
631
632 va_end(ap);
633
634 return count;
635 }
636
637 #if STDVA
Packet_scanf(sockbuf_t * sbuf,char * fmt,...)638 int Packet_scanf(sockbuf_t *sbuf, char *fmt, ...)
639 #else
640 int Packet_scanf(va_alist)
641 va_dcl
642 #endif
643 {
644 int i,
645 j,
646 *iptr,
647 count = 0,
648 failure = 0,
649 max_str_size;
650 unsigned *uptr;
651 short int *sptr;
652 unsigned short int *usptr;
653 long int *lptr;
654 unsigned long int *ulptr;
655 char *cptr,
656 *str;
657 va_list ap;
658 #if !STDVA
659 char *fmt;
660 sockbuf_t *sbuf;
661
662 va_start(ap);
663 sbuf = va_arg(ap, sockbuf_t *);
664 fmt = va_arg(ap, char *);
665 #else
666 va_start(ap, fmt);
667 #endif
668
669 for (i = j = 0; failure == 0 && fmt[i] != '\0'; i++) {
670 if (fmt[i] == '%') {
671 count++;
672 switch (fmt[++i]) {
673 case 'c':
674 if (&sbuf->buf[sbuf->len] < &sbuf->ptr[j + 1]) {
675 if (BIT(sbuf->state, SOCKBUF_DGRAM | SOCKBUF_LOCK) != 0) {
676 failure = 3;
677 break;
678 }
679 if (Sockbuf_read(sbuf) == -1) {
680 failure = 2;
681 break;
682 }
683 if (&sbuf->buf[sbuf->len] < &sbuf->ptr[j + 1]) {
684 failure = 3;
685 break;
686 }
687 }
688 cptr = va_arg(ap, char *);
689 *cptr = sbuf->ptr[j++];
690 break;
691 case 'd':
692 if (&sbuf->buf[sbuf->len] < &sbuf->ptr[j + 4]) {
693 if (BIT(sbuf->state, SOCKBUF_DGRAM | SOCKBUF_LOCK) != 0) {
694 failure = 3;
695 break;
696 }
697 if (Sockbuf_read(sbuf) == -1) {
698 failure = 2;
699 break;
700 }
701 if (&sbuf->buf[sbuf->len] < &sbuf->ptr[j + 4]) {
702 failure = 3;
703 break;
704 }
705 }
706 iptr = va_arg(ap, int *);
707 *iptr = sbuf->ptr[j++] << 24;
708 *iptr |= (sbuf->ptr[j++] & 0xFF) << 16;
709 *iptr |= (sbuf->ptr[j++] & 0xFF) << 8;
710 *iptr |= (sbuf->ptr[j++] & 0xFF);
711 break;
712 case 'u':
713 if (&sbuf->buf[sbuf->len] < &sbuf->ptr[j + 4]) {
714 if (BIT(sbuf->state, SOCKBUF_DGRAM | SOCKBUF_LOCK) != 0) {
715 failure = 3;
716 break;
717 }
718 if (Sockbuf_read(sbuf) == -1) {
719 failure = 2;
720 break;
721 }
722 if (&sbuf->buf[sbuf->len] < &sbuf->ptr[j + 4]) {
723 failure = 3;
724 break;
725 }
726 }
727 uptr = va_arg(ap, unsigned *);
728 *uptr = (sbuf->ptr[j++] & 0xFF) << 24;
729 *uptr |= (sbuf->ptr[j++] & 0xFF) << 16;
730 *uptr |= (sbuf->ptr[j++] & 0xFF) << 8;
731 *uptr |= (sbuf->ptr[j++] & 0xFF);
732 break;
733 case 'h':
734 if (&sbuf->buf[sbuf->len] < &sbuf->ptr[j + 2]) {
735 if (BIT(sbuf->state, SOCKBUF_DGRAM | SOCKBUF_LOCK) != 0) {
736 failure = 3;
737 break;
738 }
739 if (Sockbuf_read(sbuf) == -1) {
740 failure = 2;
741 break;
742 }
743 if (&sbuf->buf[sbuf->len] < &sbuf->ptr[j + 2]) {
744 failure = 3;
745 break;
746 }
747 }
748 switch (fmt[++i]) {
749 case 'd':
750 sptr = va_arg(ap, short *);
751 *sptr = sbuf->ptr[j++] << 8;
752 *sptr |= (sbuf->ptr[j++] & 0xFF);
753 break;
754 case 'u':
755 usptr = va_arg(ap, unsigned short *);
756 *usptr = (sbuf->ptr[j++] & 0xFF) << 8;
757 *usptr |= (sbuf->ptr[j++] & 0xFF);
758 break;
759 default:
760 failure = 1;
761 break;
762 }
763 break;
764 case 'l':
765 if (&sbuf->buf[sbuf->len] < &sbuf->ptr[j + 4]) {
766 if (BIT(sbuf->state, SOCKBUF_DGRAM | SOCKBUF_LOCK) != 0) {
767 failure = 3;
768 break;
769 }
770 if (Sockbuf_read(sbuf) == -1) {
771 failure = 2;
772 break;
773 }
774 if (&sbuf->buf[sbuf->len] < &sbuf->ptr[j + 4]) {
775 failure = 3;
776 break;
777 }
778 }
779 switch (fmt[++i]) {
780 case 'd':
781 lptr = va_arg(ap, long int *);
782 *lptr = sbuf->ptr[j++] << 24;
783 *lptr |= (sbuf->ptr[j++] & 0xFF) << 16;
784 *lptr |= (sbuf->ptr[j++] & 0xFF) << 8;
785 *lptr |= (sbuf->ptr[j++] & 0xFF);
786 break;
787 case 'u':
788 ulptr = va_arg(ap, unsigned long int *);
789 *ulptr = (sbuf->ptr[j++] & 0xFF) << 24;
790 *ulptr |= (sbuf->ptr[j++] & 0xFF) << 16;
791 *ulptr |= (sbuf->ptr[j++] & 0xFF) << 8;
792 *ulptr |= (sbuf->ptr[j++] & 0xFF);
793 break;
794 default:
795 failure = 1;
796 break;
797 }
798 break;
799 case 'S': /* Big strings (MSG_LEN) */
800 case 'I': /* Semi-big strings: Item name (including inscription) (ONAME_LEN) */
801 case 's': /* Small strings (MAX_CHARS) */
802 max_str_size = (fmt[i] == 'S') ? MSG_LEN : ((fmt[i] == 'I') ? ONAME_LEN : MAX_CHARS);
803 str = va_arg(ap, char *);
804 #if 1
805 int k = 0;
806 for (;;) {
807 if (&sbuf->buf[sbuf->len] < &sbuf->ptr[j + 1]) {
808 if (BIT(sbuf->state, SOCKBUF_DGRAM | SOCKBUF_LOCK) != 0) {
809 failure = 3;
810 break;
811 }
812 if (Sockbuf_read(sbuf) == -1) {
813 failure = 2;
814 break;
815 }
816 if (&sbuf->buf[sbuf->len] < &sbuf->ptr[j + 1]) {
817 failure = 3;
818 break;
819 }
820 }
821 if ((str[k++] = sbuf->ptr[j++]) == '\0') {
822 break;
823 }
824 else if (k >= max_str_size) {
825 /*
826 * What to do now is unclear to me.
827 * The server should drop the packet, but
828 * the client has more difficulty with that
829 * if this is the reliable data buffer.
830 */
831 /*
832 #ifndef SILENT
833 errno = 0;
834 plog(format("String overflow while scanning (%d,%d)",
835 k, max_str_size));
836 #endif
837 if (BIT(sbuf->state, SOCKBUF_LOCK) != 0) {
838 failure = 2;
839 } else {
840 failure = 3;
841 }
842 break;
843 */
844 /* Hack -- terminate our string and clear the sbuf -APD */
845 str[k-1] = '\0';
846 break;
847 }
848 }
849 #else
850 /* Optimized version - mikaelh */
851
852 /* Try to find a \0 in the socket buffer */
853 cptr = memchr(&sbuf->ptr[j], '\0', sbuf->len + sbuf->buf - sbuf->ptr - j);
854
855 /* Are there enough bytes in the socket buffer anyway? */
856 if (!cptr && &sbuf->ptr[j + max_str_size] <= &sbuf->buf[sbuf->len]) {
857 /* Set cptr to point to the last character */
858 cptr = &sbuf->ptr[j + max_str_size - 1];
859 }
860
861 if (!cptr) {
862 if (BIT(sbuf->state, SOCKBUF_DGRAM | SOCKBUF_LOCK) != 0) {
863 failure = 3;
864 }
865 if (Sockbuf_read(sbuf) == -1) {
866 failure = 2;
867 }
868
869 /* Try to find a \0 in the socket buffer */
870 cptr = memchr(&sbuf->ptr[j], '\0', sbuf->len + sbuf->buf - sbuf->ptr - j);
871
872 /* Are there enough bytes in the socket buffer anyway? */
873 if (!cptr && &sbuf->ptr[j + max_str_size] <= &sbuf->buf[sbuf->len]) {
874 /* Set cptr to point to the last character */
875 cptr = &sbuf->ptr[j + max_str_size - 1];
876 }
877
878 if (!cptr) {
879 failure = 3;
880 }
881 }
882
883 if (!failure) {
884 long len;
885 len = cptr - sbuf->ptr - j + 1;
886
887 /* Limit the length to max_str_size (including the \0) */
888 if (len > max_str_size) {
889 len = max_str_size;
890 }
891
892 /* Copy the string */
893 memcpy(str, &sbuf->ptr[j], len);
894
895 /* Terminate */
896 str[len - 1] = '\0';
897
898 /* Consume the entire string in the socket buffer */
899 j += len;
900 }
901 #endif
902 if (failure) {
903 strcpy(str, "ErRoR");
904 }
905 break;
906 default:
907 failure = 1;
908 break;
909 }
910 } else {
911 failure = 1;
912 }
913 }
914 if (failure == 1) {
915 errno = 0;
916 plog(format("Error in format string (%s)", fmt));
917 }
918 else if (failure == 3) {
919 /* Not enough input for one complete packet */
920 count = 0;
921 failure = 0;
922 }
923 else if (failure == 0) {
924 if (&sbuf->buf[sbuf->len] < &sbuf->ptr[j]) {
925 errno = 0;
926 plog(format("Input buffer exceeded (%s)", fmt));
927 failure = 1;
928 } else {
929 sbuf->ptr += j;
930 }
931 }
932
933 va_end(ap);
934
935 return (failure) ? -1 : count;
936 }
937
938