source: trunk/src/testing/app/vnc/sockets.cpp @ 4

Revision 4, 8.7 KB checked in by ajaworski, 13 years ago (diff)

Added modified SAGE sources

Line 
1/************************************************************************
2 *
3 *  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
4 *
5 *  This is free software; you can redistribute it and/or modify
6 *  it under the terms of the GNU General Public License as published by
7 *  the Free Software Foundation; either version 2 of the License, or
8 *  (at your option) any later version.
9 *
10 *  This software is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 *  GNU General Public License for more details.
14 *
15 *  You should have received a copy of the GNU General Public License
16 *  along with this software; if not, write to the Free Software
17 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
18 *  USA.
19 */
20
21 
22/*
23 * sockets.c - functions to deal with sockets.
24 */
25
26#include "vncviewer.h"
27
28#if defined(WIN32)
29#include <Winsock2.h>
30#include <io.h>
31#else
32#include <unistd.h>
33#include <sys/socket.h>
34#include <netinet/in.h>
35#include <netinet/tcp.h>
36#include <arpa/inet.h>
37#include <netdb.h>
38#include <fcntl.h>
39#endif
40
41#if defined(__sun)
42#include <sys/filio.h>
43#ifndef INADDR_NONE
44#define INADDR_NONE ((unsigned long) -1)
45#endif
46#endif
47
48#include <errno.h>
49#include <assert.h>
50
51
52
53#if defined(WIN32)
54void InitWinsock()
55{
56    WORD wVersionRequested;
57    WSADATA wsaData;
58    int err;
59 
60    wVersionRequested = MAKEWORD( 2, 2 );
61 
62    err = WSAStartup(wVersionRequested, &wsaData);
63    if (err != 0)
64        {
65                aError("Cannot load the valid winsock 2 dll\n");
66        exit(1);
67    }
68}
69#endif
70
71
72/*
73 * ReadFromRFBServer is called whenever we want to read some data from the RFB
74 * server.  It is non-trivial for two reasons:
75 *
76 * 1. For efficiency it performs some intelligent buffering, avoiding invoking
77 *    the read() system call too often.  For small chunks of data, it simply
78 *    copies the data out of an internal buffer.  For large amounts of data it
79 *    reads directly into the buffer provided by the caller.
80 *
81 * 2. Whenever read() would block, it invokes the Xt event dispatching
82 *    mechanism to process X events.  In fact, this is the only place these
83 *    events are processed, as there is no XtAppMainLoop in the program.
84 */
85
86
87Bool
88VNCViewer::ReadFromRFBServer(char *out, unsigned int n)
89{
90    if (n <= buffered)
91    {
92        memcpy(out, bufoutptr, n);
93        bufoutptr += n;
94        buffered -= n;
95        return True;
96    }
97
98    memcpy(out, bufoutptr, buffered);
99
100    out += buffered;
101    n -= buffered;
102
103    bufoutptr = buf;
104    buffered = 0;
105
106    if (n <= BUF_SIZE) {
107
108        while (buffered < n) {
109#if defined(WIN32)
110            int i = recv(rfbsock, buf + buffered, BUF_SIZE - buffered,0);
111#else
112            int i = read(rfbsock, buf + buffered, BUF_SIZE - buffered);
113#endif
114            if (i <= 0) {
115                if (i < 0) {
116                    if (errno == EAGAIN) {
117                        i = 0;
118                    } else {
119                        aLog("error : read1 -- i %d errno %d rfbsock %d\n",
120                                                                i, errno, rfbsock);
121                        return False;
122                    }
123                } else {
124                    aLog("VNC server closed connection\n");
125                    return False;
126                }
127            }
128            buffered += i;
129        }
130
131        memcpy(out, bufoutptr, n);
132        bufoutptr += n;
133        buffered -= n;
134        return True;
135
136    } else
137    {
138        while (n > 0) {
139#if defined(WIN32)
140            int i = recv(rfbsock, out, n, 0);
141#else
142            int i = read(rfbsock, out, n);
143#endif
144            if (i <= 0) {
145                if (i < 0) {
146                    if (errno == EAGAIN) {
147                        i = 0;
148                    } else {
149                        aLog("error : read2 -- i %d errno %d\n", i, errno);
150                        return False;
151                    }
152                } else {
153                    aLog("VNC server closed connection\n");
154                    return False;
155                }
156            }
157            out += i;
158            n -= i;
159        }
160
161        return True;
162    }
163}
164
165
166/*
167 * Write an exact number of bytes, and don't return until you've sent them.
168 */
169
170Bool
171WriteExact(int sock, char *buf, int n)
172{
173    fd_set fds;
174    int i = 0;
175    int j;
176
177    while (i < n) {
178#if defined(WIN32)
179        j = send (sock, buf + i, (n - i), 0);
180#else
181        j = write(sock, buf + i, (n - i));
182#endif
183        if (j <= 0) {
184            if (j < 0) {
185                if (errno == EAGAIN) {
186                    FD_ZERO(&fds);
187                    FD_SET(sock,&fds);
188
189                    if (select(sock+1, NULL, &fds, NULL, NULL) <= 0) {
190                        aLog("error : select");
191                        return False;
192                    }
193                    j = 0;
194                } else {
195                    aLog("error : write");
196                    return False;
197                }
198            } else {
199                aLog("write failed\n");
200                return False;
201            }
202        }
203        i += j;
204    }
205    return True;
206}
207
208
209/*
210 * ConnectToTcpAddr connects to the given TCP port.
211 */
212
213
214int
215ConnectToTcpAddr(unsigned int host, int port)
216{
217    int sock;
218    struct sockaddr_in addr;
219    int one = 1;
220
221    addr.sin_family = AF_INET;
222    addr.sin_port = htons(port);
223    addr.sin_addr.s_addr = host;
224
225    sock = socket(AF_INET, SOCK_STREAM, 0);
226    if (sock < 0) {
227        aLog("ConnectToTcpAddr: socket\n" );
228        return -1;
229    }
230
231    if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
232        aLog("ConnectToTcpAddr: connect");
233        close(sock);
234        return -1;
235    }
236
237    if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
238                   (char *)&one, sizeof(one)) < 0) {
239        aLog("ConnectToTcpAddr: setsockopt");
240        close(sock);
241        return -1;
242    }
243
244    return sock;
245}
246
247
248
249/*
250 * ListenAtTcpPort starts listening at the given TCP port.
251 */
252
253int
254ListenAtTcpPort(int port)
255{
256    int sock;
257    struct sockaddr_in addr;
258    int one = 1;
259
260    addr.sin_family = AF_INET;
261    addr.sin_port = htons(port);
262    addr.sin_addr.s_addr = INADDR_ANY;
263
264    sock = socket(AF_INET, SOCK_STREAM, 0);
265    if (sock < 0) {
266                aLog("ListenAtTcpPort: socket");
267        return -1;
268    }
269
270    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
271                   (const char *)&one, sizeof(one)) < 0) {
272        aLog("ListenAtTcpPort: setsockopt");
273        close(sock);
274        return -1;
275    }
276
277    if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
278        aLog("ListenAtTcpPort: bind");
279        close(sock);
280        return -1;
281    }
282
283    if (listen(sock, 5) < 0) {
284        aLog("ListenAtTcpPort: listen");
285        close(sock);
286        return -1;
287    }
288
289    return sock;
290}
291
292
293/*
294 * AcceptTcpConnection accepts a TCP connection.
295 */
296
297int
298AcceptTcpConnection(int listenSock)
299{
300    int sock;
301    struct sockaddr_in addr;
302#if defined(WIN32)
303    int addrlen = sizeof(addr);
304#else
305    socklen_t addrlen = sizeof(addr);
306#endif
307    int one = 1;
308
309    sock = accept(listenSock, (struct sockaddr *) &addr, &addrlen);
310    if (sock < 0) {
311                aLog("AcceptTcpConnection: accept");
312        return -1;
313    }
314
315    if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
316                   (char *)&one, sizeof(one)) < 0) {
317        aLog("AcceptTcpConnection: setsockopt");
318        close(sock);
319        return -1;
320    }
321
322    return sock;
323}
324
325
326/*
327 * SetNonBlocking sets a socket into non-blocking mode.
328 */
329
330Bool
331SetNonBlocking(int sock)
332{
333#if defined (WIN32)
334        unsigned long one = 1;
335        if (ioctlsocket (sock, FIONBIO, &one) )
336        {
337                aLog("SetNonBlocking: fcntl");
338                return False;
339        }
340        return True;
341#else
342#ifdef O_ASYNC
343    if (fcntl(sock, F_SETFL, O_ASYNC) < 0) {
344#else
345    int yes = 1;
346    if (ioctl(sock, FIOASYNC, &yes) < 0) {
347#endif
348        aLog("SetNonBlocking: fcntl");
349        return False;
350    }
351    return True;
352#endif
353}
354
355
356/*
357 * StringToIPAddr - convert a host string to an IP address.
358 */
359
360Bool
361StringToIPAddr(const char *str, unsigned long *addr)
362{
363    struct hostent *hp;
364
365    if (strcmp(str,"") == 0) {
366        *addr = 0; /* local */
367        return True;
368    }
369
370    *addr = inet_addr(str);
371
372        aLog("inet_addr %s = %d\n", str, *addr);
373
374    if (*addr != INADDR_NONE)
375        return True;
376
377    hp = gethostbyname(str);
378
379        aLog("gethostbyname %s = %x\n", str, hp);
380
381    if (hp) {
382        *addr = *(unsigned int *)hp->h_addr;
383        return True;
384    }
385
386    return False;
387}
388
389
390/*
391 * Test if the other end of a socket is on the same machine.
392 */
393
394Bool
395SameMachine(int sock)
396{
397    struct sockaddr_in peeraddr, myaddr;
398#if defined (WIN32)
399    int addrlen = sizeof(struct sockaddr_in);
400#else
401    socklen_t addrlen = sizeof(struct sockaddr_in);
402#endif
403
404    getpeername(sock, (struct sockaddr *)&peeraddr, &addrlen);
405    getsockname(sock, (struct sockaddr *)&myaddr, &addrlen);
406
407    return (peeraddr.sin_addr.s_addr == myaddr.sin_addr.s_addr);
408}
Note: See TracBrowser for help on using the repository browser.