]> git.sesse.net Git - rdpsrv/blob - Xserver/lib/font/fc/fsio.c
Support RDP5 logon packets.
[rdpsrv] / Xserver / lib / font / fc / fsio.c
1 /* $XConsortium: fsio.c,v 1.37 95/04/05 19:58:13 kaleb Exp $ */
2 /* $XFree86: xc/lib/font/fc/fsio.c,v 3.5.2.1 1998/02/15 16:08:40 hohndel Exp $ */
3 /*
4  * Copyright 1990 Network Computing Devices
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and its
7  * documentation for any purpose is hereby granted without fee, provided that
8  * the above copyright notice appear in all copies and that both that
9  * copyright notice and this permission notice appear in supporting
10  * documentation, and that the name of Network Computing Devices not be
11  * used in advertising or publicity pertaining to distribution of the
12  * software without specific, written prior permission.  Network Computing
13  * Devices makes no representations about the suitability of this software
14  * for any purpose.  It is provided "as is" without express or implied
15  * warranty.
16  *
17  * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
18  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
19  * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
20  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
23  * OR PERFORMANCE OF THIS SOFTWARE.
24  *
25  * Author:      Dave Lemke, Network Computing Devices, Inc
26  */
27 /*
28  * font server i/o routines
29  */
30
31 #ifdef WIN32
32 #define _WILLWINSOCK_
33 #endif
34
35 #include        "FS.h"
36 #include        "FSproto.h"
37
38 #include        "X11/Xtrans.h"
39 #include        "X11/Xpoll.h"
40 #include        "fontmisc.h"
41 #include        "fsio.h"
42
43 #include        <stdio.h>
44 #include        <signal.h>
45 #include        <sys/types.h>
46 #if !defined(WIN32) && !defined(AMOEBA) && !defined(_MINIX)
47 #ifndef Lynx
48 #include        <sys/socket.h>
49 #else
50 #include        <socket.h>
51 #endif
52 #endif
53 #include        <errno.h>
54 #ifdef X_NOT_STDC_ENV
55 extern int errno;
56 #endif 
57 #ifdef WIN32
58 #define EWOULDBLOCK WSAEWOULDBLOCK
59 #undef EINTR
60 #define EINTR WSAEINTR
61 #endif
62
63 #ifdef MINIX
64 #include <sys/nbio.h>
65 #define select(n,r,w,x,t) nbio_select(n,r,w,x,t)
66 #endif
67
68 #ifdef __EMX__
69 #define select(n,r,w,x,t) os2PseudoSelect(n,r,w,x,t)
70 #endif
71
72 /* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX
73  * systems are broken and return EWOULDBLOCK when they should return EAGAIN
74  */
75 #ifdef WIN32
76 #define ETEST() (WSAGetLastError() == WSAEWOULDBLOCK)
77 #else
78 #if defined(EAGAIN) && defined(EWOULDBLOCK)
79 #define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK)
80 #else
81 #ifdef EAGAIN
82 #define ETEST() (errno == EAGAIN)
83 #else
84 #define ETEST() (errno == EWOULDBLOCK)
85 #endif
86 #endif
87 #endif
88 #ifdef WIN32
89 #define ECHECK(err) (WSAGetLastError() == err)
90 #define ESET(val) WSASetLastError(val)
91 #else
92 #ifdef ISC
93 #define ECHECK(err) ((errno == err) || ETEST())
94 #else
95 #define ECHECK(err) (errno == err)
96 #endif
97 #define ESET(val) errno = val
98 #endif
99
100 static int  padlength[4] = {0, 3, 2, 1};
101 fd_set _fs_fd_mask;
102
103 int  _fs_wait_for_readable();
104
105 #ifdef SIGNALRETURNSINT
106 #define SIGNAL_T int
107 #else
108 #define SIGNAL_T void
109 #endif
110
111 /* ARGSUSED */
112 static      SIGNAL_T
113 _fs_alarm(foo)
114     int         foo;
115 {
116     return;
117 }
118
119 static XtransConnInfo
120 _fs_connect(servername, timeout)
121     char       *servername;
122     int         timeout;
123 {
124     XtransConnInfo trans_conn;          /* transport connection object */
125     int         ret = -1;
126 #ifdef SIGALRM
127     unsigned    oldTime;
128
129     SIGNAL_T(*oldAlarm) ();
130 #endif
131
132     /*
133      * Open the network connection.
134      */
135     if( (trans_conn=_FontTransOpenCOTSClient(servername)) == NULL )
136         {
137         return (NULL);
138         }
139
140 #ifdef SIGALRM
141     oldTime = alarm((unsigned) 0);
142     oldAlarm = signal(SIGALRM, _fs_alarm);
143     alarm((unsigned) timeout);
144 #endif
145
146     ret = _FontTransConnect(trans_conn,servername);
147
148 #ifdef SIGALRM
149     alarm((unsigned) 0);
150     signal(SIGALRM, oldAlarm);
151     alarm(oldTime);
152 #endif
153
154     if (ret < 0)
155         {
156         _FontTransClose(trans_conn);
157         return (NULL);
158         }
159
160     /*
161      * Set the connection non-blocking since we use select() to block.
162      */
163
164     _FontTransSetOption(trans_conn, TRANS_NONBLOCKING, 1);
165
166     return trans_conn;
167 }
168
169 static int  generationCount;
170
171 /* ARGSUSED */
172 static Bool
173 _fs_setup_connection(conn, servername, timeout, copy_name_p)
174     FSFpePtr    conn;
175     char       *servername;
176     int         timeout;
177     Bool        copy_name_p;
178 {
179     fsConnClientPrefix prefix;
180     fsConnSetup rep;
181     int         setuplength;
182     fsConnSetupAccept conn_accept;
183     int         endian;
184     int         i;
185     int         alt_len;
186     char       *auth_data = NULL,
187                *vendor_string = NULL,
188                *alt_data = NULL,
189                *alt_dst;
190     FSFpeAltPtr alts;
191     int         nalts;
192
193     if ((conn->trans_conn = _fs_connect(servername, 5)) == NULL)
194         return FALSE;
195
196     conn->fs_fd = _FontTransGetConnectionNumber (conn->trans_conn);
197
198     conn->generation = ++generationCount;
199
200     /* send setup prefix */
201     endian = 1;
202     if (*(char *) &endian)
203         prefix.byteOrder = 'l';
204     else
205         prefix.byteOrder = 'B';
206
207     prefix.major_version = FS_PROTOCOL;
208     prefix.minor_version = FS_PROTOCOL_MINOR;
209
210 /* XXX add some auth info here */
211     prefix.num_auths = 0;
212     prefix.auth_len = 0;
213
214     if (_fs_write(conn, (char *) &prefix, SIZEOF(fsConnClientPrefix)) == -1)
215         return FALSE;
216
217     /* read setup info */
218     if (_fs_read(conn, (char *) &rep, SIZEOF(fsConnSetup)) == -1)
219         return FALSE;
220
221     conn->fsMajorVersion = rep.major_version;
222     if (rep.major_version > FS_PROTOCOL)
223         return FALSE;
224
225     alts = 0;
226     /* parse alternate list */
227     if (nalts = rep.num_alternates) {
228         setuplength = rep.alternate_len << 2;
229         alts = (FSFpeAltPtr) xalloc(nalts * sizeof(FSFpeAltRec) +
230                                     setuplength);
231         if (!alts) {
232             _FontTransClose(conn->trans_conn);
233             errno = ENOMEM;
234             return FALSE;
235         }
236         alt_data = (char *) (alts + nalts);
237         if (_fs_read(conn, (char *) alt_data, setuplength) == -1) {
238             xfree(alts);
239             return FALSE;
240         }
241         alt_dst = alt_data;
242         for (i = 0; i < nalts; i++) {
243             alts[i].subset = alt_data[0];
244             alt_len = alt_data[1];
245             alts[i].name = alt_dst;
246             memmove(alt_dst, alt_data + 2, alt_len);
247             alt_dst[alt_len] = '\0';
248             alt_dst += (alt_len + 1);
249             alt_data += (2 + alt_len + padlength[(2 + alt_len) & 3]);
250         }
251     }
252     if (conn->alts)
253         xfree(conn->alts);
254     conn->alts = alts;
255     conn->numAlts = nalts;
256
257     setuplength = rep.auth_len << 2;
258     if (setuplength &&
259             !(auth_data = (char *) xalloc((unsigned int) setuplength))) {
260         _FontTransClose(conn->trans_conn);
261         errno = ENOMEM;
262         return FALSE;
263     }
264     if (_fs_read(conn, (char *) auth_data, setuplength) == -1) {
265         xfree(auth_data);
266         return FALSE;
267     }
268     if (rep.status != AuthSuccess) {
269         xfree(auth_data);
270         _FontTransClose(conn->trans_conn);
271         errno = EPERM;
272         return FALSE;
273     }
274     /* get rest */
275     if (_fs_read(conn, (char *) &conn_accept, (long) SIZEOF(fsConnSetupAccept)) == -1) {
276         xfree(auth_data);
277         return FALSE;
278     }
279     if ((vendor_string = (char *)
280          xalloc((unsigned) conn_accept.vendor_len + 1)) == NULL) {
281         xfree(auth_data);
282         _FontTransClose(conn->trans_conn);
283         errno = ENOMEM;
284         return FALSE;
285     }
286     if (_fs_read_pad(conn, (char *) vendor_string, conn_accept.vendor_len) == -1) {
287         xfree(vendor_string);
288         xfree(auth_data);
289         return FALSE;
290     }
291     xfree(auth_data);
292     xfree(vendor_string);
293
294     if (copy_name_p)
295     {
296         conn->servername = (char *) xalloc(strlen(servername) + 1);
297         if (conn->servername == NULL)
298             return FALSE;
299         strcpy(conn->servername, servername);
300     }
301     else
302         conn->servername = servername;
303
304     return TRUE;
305 }
306
307 static Bool
308 _fs_try_alternates(conn, timeout)
309     FSFpePtr    conn;
310     int         timeout;
311 {
312     int         i;
313
314     for (i = 0; i < conn->numAlts; i++)
315         if (_fs_setup_connection(conn, conn->alts[i].name, timeout, TRUE))
316             return TRUE;
317     return FALSE;
318 }
319
320 #define FS_OPEN_TIMEOUT     30
321 #define FS_REOPEN_TIMEOUT   10
322
323 FSFpePtr
324 _fs_open_server(servername)
325     char       *servername;
326 {
327     FSFpePtr    conn;
328
329     conn = (FSFpePtr) xalloc(sizeof(FSFpeRec));
330     if (!conn) {
331         errno = ENOMEM;
332         return (FSFpePtr) NULL;
333     }
334     bzero((char *) conn, sizeof(FSFpeRec));
335     if (!_fs_setup_connection(conn, servername, FS_OPEN_TIMEOUT, TRUE)) {
336         if (!_fs_try_alternates(conn, FS_OPEN_TIMEOUT)) {
337             xfree(conn->alts);
338             xfree(conn);
339             return (FSFpePtr) NULL;
340         }
341     }
342     return conn;
343 }
344
345 Bool
346 _fs_reopen_server(conn)
347     FSFpePtr    conn;
348 {
349     if (_fs_setup_connection(conn, conn->servername, FS_REOPEN_TIMEOUT, FALSE))
350         return TRUE;
351     if (_fs_try_alternates(conn, FS_REOPEN_TIMEOUT))
352         return TRUE;
353     return FALSE;
354 }
355
356 /*
357  * expects everything to be here.  *not* to be called when reading huge
358  * numbers of replies, but rather to get each chunk
359  */
360 _fs_read(conn, data, size)
361     FSFpePtr    conn;
362     char       *data;
363     unsigned long size;
364 {
365     long        bytes_read;
366 #if defined(SVR4) && defined(i386)
367     int         num_failed_reads = 0;
368 #endif
369
370     if (size == 0) {
371
372 #ifdef DEBUG
373         fprintf(stderr, "tried to read 0 bytes \n");
374 #endif
375
376         return 0;
377     }
378     ESET(0);
379     /*
380      * For SVR4 with a unix-domain connection, ETEST() after selecting
381      * readable means the server has died.  To do this here, we look for
382      * two consecutive reads returning ETEST().
383      */
384     while ((bytes_read = _FontTransRead(conn->trans_conn,
385         data, (int) size)) != size) {
386         if (bytes_read > 0) {
387             size -= bytes_read;
388             data += bytes_read;
389 #if defined(SVR4) && defined(i386)
390             num_failed_reads = 0;
391 #endif
392         } else if (ETEST()) {
393             /* in a perfect world, this shouldn't happen */
394             /* ... but then, its less than perfect... */
395             if (_fs_wait_for_readable(conn) == -1) {    /* check for error */
396                 _fs_connection_died(conn);
397                 ESET(EPIPE);
398                 return -1;
399             }
400 #if defined(SVR4) && defined(i386)
401             num_failed_reads++;
402             if (num_failed_reads > 1) {
403                 _fs_connection_died(conn);
404                 ESET(EPIPE);
405                 return -1;
406             }
407 #endif
408             ESET(0);
409         } else if (ECHECK(EINTR)) {
410 #if defined(SVR4) && defined(i386)
411             num_failed_reads = 0;
412 #endif
413             continue;
414         } else {                /* something bad happened */
415             if (conn->fs_fd > 0)
416                 _fs_connection_died(conn);
417             ESET(EPIPE);
418             return -1;
419         }
420     }
421     return 0;
422 }
423
424 _fs_write(conn, data, size)
425     FSFpePtr    conn;
426     char       *data;
427     unsigned long size;
428 {
429     long        bytes_written;
430
431     if (size == 0) {
432
433 #ifdef DEBUG
434         fprintf(stderr, "tried to write 0 bytes \n");
435 #endif
436
437         return 0;
438     }
439
440     /* XXX - hack.  The right fix is to remember that the font server
441        has gone away when we first discovered it. */
442     if (!conn->trans_conn)
443         return -1;
444
445     ESET(0);
446     while ((bytes_written = _FontTransWrite(conn->trans_conn,
447         data, (int) size)) != size) {
448         if (bytes_written > 0) {
449             size -= bytes_written;
450             data += bytes_written;
451         } else if (ETEST()) {
452             /* XXX -- we assume this can't happen */
453
454 #ifdef DEBUG
455             fprintf(stderr, "fs_write blocking\n");
456 #endif
457         } else if (ECHECK(EINTR)) {
458             continue;
459         } else {                /* something bad happened */
460             _fs_connection_died(conn);
461             ESET(EPIPE);
462             return -1;
463         }
464     }
465     return 0;
466 }
467
468 _fs_read_pad(conn, data, len)
469     FSFpePtr    conn;
470     char       *data;
471     int         len;
472 {
473     char        pad[3];
474
475     if (_fs_read(conn, data, len) == -1)
476         return -1;
477
478     /* read the junk */
479     if (padlength[len & 3]) {
480         return _fs_read(conn, pad, padlength[len & 3]);
481     }
482     return 0;
483 }
484
485 _fs_write_pad(conn, data, len)
486     FSFpePtr    conn;
487     char       *data;
488     int         len;
489 {
490     static char pad[3];
491
492     if (_fs_write(conn, data, len) == -1)
493         return -1;
494
495     /* write the pad */
496     if (padlength[len & 3]) {
497         return _fs_write(conn, pad, padlength[len & 3]);
498     }
499     return 0;
500 }
501
502 /*
503  * returns the amount of data waiting to be read
504  */
505 int
506 _fs_data_ready(conn)
507     FSFpePtr    conn;
508 {
509     BytesReadable_t readable;
510
511     if (_FontTransBytesReadable(conn->trans_conn, &readable) < 0)
512         return -1;
513     return readable;
514 }
515
516 int
517 _fs_wait_for_readable(conn)
518     FSFpePtr    conn;
519 {
520 #ifndef AMOEBA
521     fd_set r_mask;
522     fd_set e_mask;
523     int         result;
524
525 #ifdef DEBUG
526     fprintf(stderr, "read would block\n");
527 #endif
528
529     do {
530         FD_ZERO(&r_mask);
531 #ifndef MINIX
532         FD_ZERO(&e_mask);
533 #endif
534         FD_SET(conn->fs_fd, &r_mask);
535         FD_SET(conn->fs_fd, &e_mask);
536         result = Select(conn->fs_fd + 1, &r_mask, NULL, &e_mask, NULL);
537         if (result == -1) {
538             if (ECHECK(EINTR) || ECHECK(EAGAIN))
539                 continue;
540             else
541                 return -1;
542         }
543         if (result && FD_ISSET(conn->fs_fd, &e_mask))
544             return -1;
545     } while (result <= 0);
546
547     return 0;
548 #else
549     printf("fs_wait_for_readable(): fail\n");
550     return -1;
551 #endif
552 }
553
554 int
555 _fs_set_bit(mask, fd)
556     fd_set* mask;
557     int         fd;
558 {
559     FD_SET(fd, mask);
560     return fd;
561 }
562
563 int
564 _fs_is_bit_set(mask, fd)
565     fd_set* mask;
566     int         fd;
567 {
568     return FD_ISSET(fd, mask);
569 }
570
571 void
572 _fs_bit_clear(mask, fd)
573     fd_set* mask;
574     int         fd;
575 {
576     FD_CLR(fd, mask);
577 }
578
579 int
580 _fs_any_bit_set(mask)
581     fd_set* mask;
582 {
583     XFD_ANYSET(mask);
584 }
585
586 int
587 _fs_or_bits(dst, m1, m2)
588     fd_set* dst;
589     fd_set* m1;
590     fd_set* m2;
591 {
592 #ifdef WIN32
593     int i;
594     if (dst != m1) {
595         for (i = m1->fd_count; --i >= 0; ) {
596             if (!FD_ISSET(m1->fd_array[i], dst))
597                 FD_SET(m1->fd_array[i], dst);
598         }
599     }
600     if (dst != m2) {
601         for (i = m2->fd_count; --i >= 0; ) {
602             if (!FD_ISSET(m2->fd_array[i], dst))
603                 FD_SET(m2->fd_array[i], dst);
604         }
605     }
606 #else
607     XFD_ORSET(dst, m1, m2);
608 #endif
609 }
610
611 _fs_drain_bytes(conn, len)
612     FSFpePtr    conn;
613     int         len;
614 {
615     char        buf[128];
616
617 #ifdef DEBUG
618     fprintf(stderr, "draining wire\n");
619 #endif
620
621     while (len > 0) {
622         if (_fs_read(conn, buf, (len < 128) ? len : 128) < 0)
623             return -1;
624         len -= 128;
625     }
626     return 0;
627 }
628
629 _fs_drain_bytes_pad(conn, len)
630     FSFpePtr    conn;
631     int         len;
632 {
633     _fs_drain_bytes(conn, len);
634
635     /* read the junk */
636     if (padlength[len & 3]) {
637         _fs_drain_bytes(conn, padlength[len & 3]);
638     }
639 }
640
641 _fs_eat_rest_of_error(conn, err)
642     FSFpePtr    conn;
643     fsError    *err;
644 {
645     int         len = (err->length - (SIZEOF(fsGenericReply) >> 2)) << 2;
646
647 #ifdef DEBUG
648     fprintf(stderr, "clearing error\n");
649 #endif
650
651     _fs_drain_bytes(conn, len);
652 }