VirtualBox

source: vbox/trunk/src/VBox/GuestHost/OpenGL/util/udptcpip.c@ 53726

最後變更 在這個檔案從53726是 53726,由 vboxsync 提交於 10 年 前

properties.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 18.1 KB
 
1/* Copyright (c) 2001, Stanford University
2 * All rights reserved
3 *
4 * See the file LICENSE.txt for information on redistributing this software.
5 */
6
7#ifdef WINDOWS
8#define WIN32_LEAN_AND_MEAN
9#pragma warning( push, 3 )
10#include <winsock2.h>
11#include <ws2tcpip.h> /* for ipv6 */
12#include <time.h>
13#pragma warning( pop )
14#pragma warning( disable : 4514 )
15#pragma warning( disable : 4127 )
16# ifndef VBOX
17typedef int ssize_t;
18# endif
19#define write(a,b,c) send(a,b,c,0)
20#else
21#include <sys/types.h>
22#if defined(OSF1)
23typedef int socklen_t;
24#endif
25#include <sys/socket.h>
26#include <sys/time.h>
27#include <sys/ioctl.h>
28#ifdef LINUX
29#define IP_MTU 14
30#endif
31#include <netinet/in.h>
32#if !defined(IRIX) /* ip6.h might not be present on other unix variants either */
33#include <netinet/ip6.h>
34#endif
35#include <netinet/udp.h>
36#ifndef DARWIN
37#include <netinet/tcp.h>
38#endif
39#include <arpa/inet.h>
40#include <netdb.h>
41#include <unistd.h>
42#endif
43
44#include <limits.h>
45#include <stdlib.h>
46#include <stdio.h>
47#include <errno.h>
48#include <signal.h>
49#include <string.h>
50#ifdef AIX
51#include <strings.h>
52#endif
53
54#include "cr_error.h"
55#include "cr_mem.h"
56#include "cr_string.h"
57#include "cr_bufpool.h"
58#include "cr_net.h"
59#include "cr_endian.h"
60#include "cr_threads.h"
61#include "net_internals.h"
62
63#ifdef ADDRINFO
64#define PF PF_UNSPEC
65#endif
66
67#ifndef MSG_TRUNC
68#define MSG_TRUNC 0
69#endif
70
71#ifdef IRIX
72/* IRIX defines this token, but appears to be missing the related types
73 * and functions. Turn it off.
74 */
75#undef AF_INET6
76#endif
77
78#if defined( WINDOWS ) || defined( IRIX ) || defined( IRIX64 )
79typedef int socklen_t;
80#endif
81
82static void
83crUDPIPWriteExact( CRConnection *conn, const void *buf, unsigned int len )
84{
85 int retval;
86 if ( len > conn->mtu + sizeof(conn->seq) )
87 {
88 crWarning( "crUDPIPWriteExact(%d): too big a packet for mtu %d, dropping !", len, (int)(conn->mtu + sizeof(conn->seq)) );
89 return;
90 }
91 retval = sendto( conn->udp_socket, buf, len, 0,
92 (struct sockaddr *) &(conn->remoteaddr), sizeof(conn->remoteaddr));
93 if ( retval <= 0 )
94 {
95 int err = crTCPIPErrno( );
96 crWarning( "crUDPIPWriteExact(%d): %s", len, crTCPIPErrorString( err ) );
97#ifdef LINUX
98 if ( err == EMSGSIZE )
99 {
100 int opt;
101 socklen_t leno = sizeof(opt);
102 crDebug( "Too big a UDP packet(%d), looking at new MTU...", len );
103 if ( getsockopt( conn->udp_socket, SOL_IP, IP_MTU_DISCOVER, &opt, &leno) == -1)
104 {
105 err = crTCPIPErrno( );
106 crWarning( "Couldn't determine whether PMTU discovery is used : %s", crTCPIPErrorString( err ) );
107 return;
108 }
109 if ( leno != sizeof(opt) )
110 {
111 crWarning( "Unexpected length %d for PMTU_DISCOVERY option length", leno );
112 return;
113 }
114 if ( opt == IP_PMTUDISC_DONT )
115 {
116 crWarning( "Uh, PMTU discovery isn't enabled ?!" );
117 return;
118 }
119 if ( getsockopt( conn->udp_socket, SOL_IP, IP_MTU, &opt, &leno) == -1 )
120 {
121 err = crTCPIPErrno( );
122 crWarning( "Couldn't determine the MTU : %s", crTCPIPErrorString( err ) );
123 return;
124 }
125 if ( leno != sizeof(opt) )
126 {
127 crWarning( "Unexpected length %d for MTU option length", leno );
128 return;
129 }
130 opt -= sizeof(conn->seq) + sizeof(struct udphdr) + sizeof(struct ip6_hdr);
131 if (opt >= (int) conn->mtu)
132 {
133 crWarning( "But MTU discovery is still bigger ! Narrowing it by hand to %d", conn->mtu = (conn->mtu * 2 / 3) & ~0x3 );
134 }
135 else
136 {
137 crDebug( "new MTU is %d", opt );
138 conn->mtu = opt & ~0x3;
139 }
140 }
141#endif
142 }
143}
144
145static void
146crUDPTCPIPAccept( CRConnection *conn, const char *hostname, unsigned short port )
147{
148 int err;
149 socklen_t addr_length;
150#ifndef ADDRINFO
151 struct sockaddr addr;
152 struct sockaddr_in udpaddr;
153#else
154 struct sockaddr_storage addr;
155 struct addrinfo *res,*cur;
156 struct addrinfo hints;
157#endif
158
159 crTCPIPAccept( conn, hostname, port );
160
161#ifndef ADDRINFO
162 conn->udp_socket = socket( AF_INET, SOCK_DGRAM, 0 );
163 if ( conn->udp_socket >= 0 )
164 {
165 memset(&udpaddr, 0, sizeof(udpaddr));
166 udpaddr.sin_family = AF_INET;
167 udpaddr.sin_addr.s_addr = INADDR_ANY;
168 udpaddr.sin_port = htons(0);
169 if ( bind( conn->udp_socket, (struct sockaddr *) &udpaddr, sizeof(udpaddr) ) )
170 {
171 err = crTCPIPErrno( );
172 crWarning( "Couldn't bind socket: %s", crTCPIPErrorString( err ) );
173 crCloseSocket( conn->udp_socket );
174 conn->udp_socket = -1;
175 }
176 }
177#else
178 memset(&hints, 0, sizeof(hints));
179 hints.ai_flags = AI_PASSIVE;
180 hints.ai_family = PF;
181 hints.ai_socktype = SOCK_DGRAM;
182
183 err = getaddrinfo( NULL, "0", &hints, &res);
184 if ( err )
185 crError( "Couldn't find local UDP port: %s", gai_strerror(err));
186
187 conn->udp_socket = -1;
188
189 for (cur=res;cur;cur=cur->ai_next)
190 {
191 conn->udp_socket = socket( cur->ai_family, cur->ai_socktype, cur->ai_protocol );
192 if ( conn->udp_socket == -1 )
193 {
194 err = crTCPIPErrno( );
195 if (err != EAFNOSUPPORT)
196 crWarning( "Couldn't create socket of family %i: %s, trying another one", cur->ai_family, crTCPIPErrorString( err ) );
197 continue;
198 }
199 if ( bind( conn->udp_socket, cur->ai_addr, cur->ai_addrlen ) )
200 {
201 err = crTCPIPErrno( );
202 crWarning( "Couldn't bind socket: %s", crTCPIPErrorString( err ) );
203 crCloseSocket( conn->udp_socket );
204 conn->udp_socket = -1;
205 continue;
206 }
207 break;
208
209 }
210 freeaddrinfo(res);
211#endif
212
213 if ( conn->udp_socket < 0 )
214 crError( "Couldn't find local UDP port" );
215
216 addr_length = sizeof(addr);
217 err = getsockname( conn->udp_socket, (struct sockaddr *) &addr, &addr_length );
218
219 if ( err == -1 )
220 crError( "Couldn't get our local UDP port: %s", crTCPIPErrorString( crTCPIPErrno( ) ) );
221
222 switch (((struct sockaddr *) &addr)->sa_family) {
223 case AF_INET:
224 crTCPIPWriteExact( conn, &((struct sockaddr_in *)&addr)->sin_port,
225 sizeof(((struct sockaddr_in *)&addr)->sin_port));
226 break;
227#ifdef AF_INET6
228 case AF_INET6:
229 crTCPIPWriteExact( conn, &((struct sockaddr_in6 *)&addr)->sin6_port,
230 sizeof(((struct sockaddr_in6 *)&addr)->sin6_port));
231 break;
232#endif
233 default:
234 crError( "Unknown address family: %d", ((struct sockaddr *) &addr)->sa_family);
235 }
236}
237
238
239static unsigned int safelen=0;
240static void crUDPTCPIPSend( CRConnection *conn, void **bufp,
241 const void *start, unsigned int len )
242{
243 static unsigned int safedone=0;
244 CRTCPIPBuffer *udptcpip_buffer;
245 unsigned int *lenp;
246
247 if ( !conn || conn->type == CR_NO_CONNECTION )
248 return;
249
250 if ( safelen+len > safelen )
251 {
252 safelen+=len;
253 if (safelen-safedone>100000)
254 {
255 safedone=safelen;
256 crDebug( "%dKo safe", safelen/1024 );
257 }
258 }
259
260 conn->seq++;
261 if ( bufp == NULL )
262 {
263 unsigned int len_swap = conn->swap ? SWAP32(len) : len;
264 /* we are doing synchronous sends from user memory, so no need
265 * to get fancy. Simply write the length & the payload and
266 * return. */
267 crTCPIPWriteExact( conn, &len_swap, sizeof(len_swap) );
268 if ( !conn || conn->type == CR_NO_CONNECTION ) return;
269 crTCPIPWriteExact( conn, start, len );
270 return;
271 }
272
273 udptcpip_buffer = (CRTCPIPBuffer *)(*bufp) - 1;
274
275 CRASSERT( udptcpip_buffer->magic == CR_TCPIP_BUFFER_MAGIC );
276
277 /* All of the buffers passed to the send function were allocated
278 * with crTCPIPAlloc(), which includes a header with a 4 byte
279 * length field, to insure that we always have a place to write
280 * the length field, even when start == *bufp. */
281 lenp = (unsigned int *) start - 1;
282 if (conn->swap)
283 {
284 *lenp = SWAP32(len);
285 }
286 else
287 {
288 *lenp = len;
289 }
290
291 if ( __tcpip_write_exact( conn->tcp_socket, lenp, len + sizeof(*lenp) ) < 0 )
292 {
293 __tcpip_dead_connection( conn );
294 }
295
296 /* reclaim this pointer for reuse and try to keep the client from
297 accidentally reusing it directly */
298#ifdef CHROMIUM_THREADSAFE
299 crLockMutex(&cr_tcpip.mutex);
300#endif
301 crBufferPoolPush( cr_tcpip.bufpool, udptcpip_buffer, conn->buffer_size );
302 /* Since the buffer's now in the 'free' buffer pool, the caller can't
303 * use it any more. Setting bufp to NULL will make sure the caller
304 * doesn't try to re-use the buffer.
305 */
306 *bufp = NULL;
307#ifdef CHROMIUM_THREADSAFE
308 crUnlockMutex(&cr_tcpip.mutex);
309#endif
310}
311
312static unsigned int barflen=0;
313static void crUDPTCPIPBarf( CRConnection *conn, void **bufp,
314 const void *start, unsigned int len)
315{
316 static unsigned int barfdone=0;
317 static const unsigned int sizes[]={
318 0,10,50,100,500,1000,5000,10000,UINT_MAX
319 };
320 static unsigned int nbs[sizeof(sizes)/sizeof(int)] = {
321 0, 0, 0, 0, 0, 0, 0, 0, 0
322 };
323 static unsigned int nb;
324 unsigned int *seqp;
325 CRTCPIPBuffer *udptcpip_buffer;
326 int i;
327
328 if (!bufp) {
329 crDebug("writing safely %d bytes because from user memory",len);
330 crUDPTCPIPSend( conn, bufp, start, len);
331 return;
332 }
333 if (len > conn->mtu) {
334 crDebug("writing safely %d bytes because that is too much for MTU %d", len, conn->mtu);
335 crUDPTCPIPSend( conn, bufp, start, len);
336 return;
337 }
338
339 if ( barflen+len > barflen )
340 {
341 barflen+=len;
342 nb++;
343 for(i=0;;i++)
344 if (len > sizes[i] && len <= sizes[i+1]) {
345 nbs[i]++;
346 break;
347 }
348 if (barflen-barfdone>1<<22) {
349 barfdone=barflen;
350 crDebug( "send traffic: %d%sMo barfed %dKo safe", barflen/(1024*1024), barflen?"":".0", safelen/1024 );
351 if (nb) {
352 for (i=0; i < (int) (sizeof(sizes)/sizeof(int)-1); i++)
353 fprintf(stderr,"%u:%u%s%% ",sizes[i],(nbs[i]*100)/nb,nbs[i]==0?".0":"");
354 fprintf(stderr,"\n");
355 }
356 }
357 }
358
359 udptcpip_buffer = (CRTCPIPBuffer *)(*bufp) - 1;
360
361 CRASSERT( udptcpip_buffer->magic == CR_TCPIP_BUFFER_MAGIC );
362
363 seqp = (unsigned int *) start - 1;
364 if (conn->swap)
365 {
366 *seqp = SWAP32(conn->seq);
367 }
368 else
369 {
370 *seqp = conn->seq;
371 }
372 crUDPIPWriteExact( conn, seqp, len + sizeof(*seqp) );
373
374 /* reclaim this pointer for reuse and try to keep the client from
375 accidentally reusing it directly */
376#ifdef CHROMIUM_THREADSAFE
377 crLockMutex(&cr_tcpip.mutex);
378#endif
379 crBufferPoolPush( cr_tcpip.bufpool, udptcpip_buffer, conn->buffer_size );
380#ifdef CHROMIUM_THREADSAFE
381 crUnlockMutex(&cr_tcpip.mutex);
382#endif
383 *bufp = NULL;
384}
385
386static void
387crUDPTCPIPReceive( CRConnection *conn, CRTCPIPBuffer *buf, int len )
388{
389 CRMessage *msg;
390 CRMessageType cached_type;
391#if 0
392 crLogRead( len );
393#endif
394
395 conn->recv_credits -= len;
396
397 conn->total_bytes_recv += len;
398
399 msg = (CRMessage *) (buf + 1);
400 cached_type = msg->header.type;
401 if (conn->swap)
402 {
403 msg->header.type = (CRMessageType) SWAP32( msg->header.type );
404 msg->header.conn_id = (CRMessageType) SWAP32( msg->header.conn_id );
405 }
406
407 crNetDispatchMessage( cr_tcpip.recv_list, conn, msg, len );
408
409 /* CR_MESSAGE_OPCODES is freed in
410 * crserverlib/server_stream.c
411 *
412 * OOB messages are the programmer's problem. -- Humper 12/17/01 */
413 if (cached_type != CR_MESSAGE_OPCODES && cached_type != CR_MESSAGE_OOB)
414 {
415 crTCPIPFree( conn, buf + 1 );
416 }
417}
418
419int
420crUDPTCPIPRecv( void )
421{
422 int num_ready, max_fd;
423 fd_set read_fds;
424 int i;
425 /* ensure we don't get caught with a new thread connecting */
426 int num_conns = cr_tcpip.num_conns;
427
428#ifdef CHROMIUM_THREADSAFE
429 crLockMutex(&cr_tcpip.recvmutex);
430#endif
431
432 max_fd = 0;
433 FD_ZERO( &read_fds );
434 for ( i = 0; i < num_conns; i++ )
435 {
436 CRConnection *conn = cr_tcpip.conns[i];
437 if ( !conn || conn->type == CR_NO_CONNECTION ) continue;
438 if ( conn->recv_credits > 0 || conn->type != CR_UDPTCPIP )
439 {
440 /*
441 * NOTE: may want to always put the FD in the descriptor
442 * set so we'll notice broken connections. Down in the
443 * loop that iterates over the ready sockets only peek
444 * (MSG_PEEK flag to recv()?) if the connection isn't
445 * enabled.
446 */
447 CRSocket sock = conn->tcp_socket;
448
449 if (conn->type != CR_UDPTCPIP)
450 continue;
451
452 if ( (int) sock + 1 > max_fd )
453 max_fd = (int) sock + 1;
454 FD_SET( sock, &read_fds );
455
456 sock = conn->udp_socket;
457 if ( (int) sock + 1 > max_fd )
458 max_fd = (int) sock + 1;
459 FD_SET( sock, &read_fds );
460 }
461 }
462
463 if (!max_fd) {
464#ifdef CHROMIUM_THREADSAFE
465 crUnlockMutex(&cr_tcpip.recvmutex);
466#endif
467 return 0;
468 }
469
470 if ( num_conns )
471 {
472 num_ready = __crSelect( max_fd, &read_fds, 0, 500 );
473 }
474 else
475 {
476 crWarning( "Waiting for first connection..." );
477 num_ready = __crSelect( max_fd, &read_fds, 0, 0 );
478 }
479
480 if ( num_ready == 0 ) {
481#ifdef CHROMIUM_THREADSAFE
482 crUnlockMutex(&cr_tcpip.recvmutex);
483#endif
484 return 0;
485 }
486
487 for ( i = 0; i < num_conns; i++ )
488 {
489 CRConnection *conn = cr_tcpip.conns[i];
490 CRTCPIPBuffer *buf;
491 int len;
492 int sock;
493
494 if ( !conn || conn->type == CR_NO_CONNECTION ) continue;
495
496 if ( conn->type != CR_UDPTCPIP )
497 continue;
498
499 if ( conn->udp_packet ) {
500 unsigned int *seq;
501 buf = conn->udp_packet;
502 seq = (unsigned int *)(buf + 1) - 1;
503 if ( *seq == conn->ack )
504 {
505 crUDPTCPIPReceive( conn, buf,
506 conn->udp_packetlen );
507 conn->udp_packet = NULL;
508 i--; /* can now read other packets */
509 continue;
510 }
511 if ( *seq - conn->ack > (~(0U)) >> 1 )
512 {
513 crError( "%u is older than %u ?!", *seq, conn->ack );
514 crTCPIPFree( conn, buf + 1 );
515 conn->udp_packet = NULL;
516 i--; /* can now read other packets */
517 continue;
518 }
519 /* still too early, wait for TCP data */
520 }
521 else if ( FD_ISSET(conn->udp_socket, &read_fds ) )
522 {
523 CRTCPIPBuffer *buf = ((CRTCPIPBuffer *) crTCPIPAlloc( conn )) - 1;
524 unsigned int *seq = ((unsigned int *) (buf + 1)) - 1;
525 int len;
526
527 len = recv( conn->udp_socket, (void *)seq,
528 buf->allocated + sizeof(*seq), MSG_TRUNC );
529
530 CRASSERT( len > 0 );
531 CRASSERT( (unsigned int)len <= buf->allocated + sizeof(*seq) );
532 if ( len < (int) sizeof(*seq) )
533 {
534 crWarning( "too short a UDP packet : %d", len);
535 crTCPIPFree( conn, buf + 1 );
536 continue;
537 }
538
539 buf->len = len;
540
541 if ( *seq == conn->ack)
542 {
543 crUDPTCPIPReceive( conn, buf, len );
544 continue;
545 }
546
547 if ( *seq - conn->ack > (~(0U)) >> 1 )
548 {
549 crWarning( "%u is older than %u, dropping", *seq, conn->ack );
550 crTCPIPFree( conn, buf + 1 );
551 continue;
552 }
553 conn->udp_packet = buf;
554 conn->udp_packetlen = len;
555 }
556
557 sock = conn->tcp_socket;
558 if ( !FD_ISSET( sock, &read_fds ) )
559 continue;
560
561 if ( __tcpip_read_exact( sock, &len, sizeof(len)) <= 0 )
562 {
563 __tcpip_dead_connection( conn );
564 i--;
565 continue;
566 }
567
568 if (conn->swap)
569 {
570 len = SWAP32(len);
571 }
572
573 CRASSERT( len > 0 );
574
575 if ( (unsigned int)len <= conn->buffer_size )
576 {
577 buf = (CRTCPIPBuffer *) crTCPIPAlloc( conn ) - 1;
578 }
579 else
580 {
581 buf = (CRTCPIPBuffer *)
582 crAlloc( sizeof(*buf) + len );
583 buf->magic = CR_TCPIP_BUFFER_MAGIC;
584 buf->kind = CRTCPIPMemoryBig;
585 buf->pad = 0;
586 }
587
588 buf->len = len;
589
590 if ( __tcpip_read_exact( sock, buf + 1, len ) <= 0 )
591 {
592 crWarning( "Bad juju: %d %d", buf->allocated, len );
593 crFree( buf );
594 __tcpip_dead_connection( conn );
595 i--;
596 continue;
597 }
598
599 crUDPTCPIPReceive( conn, buf, len );
600 conn->ack++;
601 }
602
603#ifdef CHROMIUM_THREADSAFE
604 crUnlockMutex(&cr_tcpip.recvmutex);
605#endif
606
607 return 1;
608}
609
610void crUDPTCPIPInit( CRNetReceiveFuncList *rfl, CRNetCloseFuncList *cfl, unsigned int mtu )
611{
612 crTCPIPInit( rfl, cfl, mtu );
613}
614
615/* The function that actually connects. This should only be called by clients
616 * Servers have another way to set up the socket. */
617
618static int crUDPTCPIPDoConnect( CRConnection *conn )
619{
620#ifdef WINDOWS
621 unsigned short port;
622#else
623 in_port_t port;
624#endif
625#ifdef LINUX
626 int opt = IP_PMTUDISC_DO;
627#endif
628#ifndef ADDRINFO
629 struct hostent *hp;
630#else
631 int err;
632 char port_s[NI_MAXSERV];
633 struct addrinfo *res,*cur;
634 struct addrinfo hints;
635#endif
636
637 /* first connect to its tcp port */
638 if ( !crTCPIPDoConnect( conn ) )
639 return 0;
640
641 /* read its UDP port */
642 crTCPIPReadExact( conn, &port, sizeof( port ) );
643 port = ntohs(port);
644
645 crDebug( "Server's UDP port is %d", port);
646
647 /* and connect to it */
648#ifndef ADDRINFO
649 hp = gethostbyname( conn->hostname );
650 if ( !hp )
651 {
652 crWarning( "Unknown host: \"%s\"", conn->hostname );
653 return 0;
654 }
655 conn->udp_socket = socket( AF_INET, SOCK_DGRAM, 0 );
656 memset(&conn->remoteaddr, 0, sizeof(conn->remoteaddr));
657 conn->remoteaddr.sin_family = AF_INET;
658 conn->remoteaddr.sin_port = htons( (short) port );
659
660 memcpy( (char *) &conn->remoteaddr.sin_addr, hp->h_addr,
661 sizeof(conn->remoteaddr.sin_addr) );
662 if ( conn->udp_socket >= 0 ) {
663 if ( connect( conn->udp_socket, (struct sockaddr *) &conn->remoteaddr,
664 sizeof(conn->remoteaddr) ) == -1 )
665 crWarning( "Couldn't connect UDP socket : %s", crTCPIPErrorString( crTCPIPErrno( ) ) );
666 } else {
667#else
668 sprintf(port_s, "%u", port);
669
670 memset(&hints, 0, sizeof(hints));
671 hints.ai_family = PF;
672 hints.ai_socktype = SOCK_DGRAM;
673
674 err = getaddrinfo( conn->hostname, port_s, &hints, &res);
675 if ( err )
676 {
677 crWarning( "Unknown host: \"%s\": %s", conn->hostname, gai_strerror(err) );
678 return 0;
679 }
680
681 for (cur=res;cur;)
682 {
683 conn->udp_socket = socket( cur->ai_family, cur->ai_socktype, cur->ai_protocol );
684 if ( conn->udp_socket >= 0 )
685 {
686 if ( connect( conn->udp_socket, cur->ai_addr, cur->ai_addrlen ) == -1 )
687 crWarning( "Couldn't connect UDP socket : %s", crTCPIPErrorString( crTCPIPErrno( ) ) );
688 break;
689 }
690 err = crTCPIPErrno( );
691 if (err != EAFNOSUPPORT)
692 crWarning( "socket error: %s, trying another way", crTCPIPErrorString( err ) );
693 cur=cur->ai_next;
694 }
695 if (!cur) {
696 freeaddrinfo(res);
697#endif
698 crWarning( "Couldn't find any suitable way to connect to %s:%d", conn->hostname, port );
699 return 0;
700 }
701
702#ifdef LINUX
703 if ( setsockopt(conn->udp_socket, SOL_IP, IP_MTU_DISCOVER, &opt, sizeof(opt)) == -1 )
704 {
705 err = crTCPIPErrno( );
706 crWarning( "MTU discovery can't be activated : %s", crTCPIPErrorString( err ) );
707 }
708 else
709 {
710 socklen_t len = sizeof(opt);
711 if ( getsockopt(conn->udp_socket, SOL_IP, IP_MTU, &opt, &len) == -1 )
712 crWarning( "MTU couldn't be got : %s", crTCPIPErrorString( crTCPIPErrno ( ) ) );
713 else
714 if ( len != sizeof(opt) )
715 crWarning( "Unexpected length %d for MTU option length", len );
716 else
717 {
718 opt -= sizeof(conn->seq) + sizeof(struct udphdr) + sizeof(struct ip6_hdr);
719 crDebug( "MTU is (for now) %d", opt );
720 conn->mtu = opt;
721 }
722 }
723#endif
724#ifdef ADDRINFO
725 crMemcpy(&conn->remoteaddr, cur->ai_addr, cur->ai_addrlen);
726 freeaddrinfo(res);
727#endif
728 return 1;
729}
730
731static void crUDPTCPIPDoDisconnect( CRConnection *conn )
732{
733 crCloseSocket( conn->udp_socket );
734 crTCPIPDoDisconnect( conn );
735}
736
737void crUDPTCPIPConnection( CRConnection *conn )
738{
739 crTCPIPConnection( conn );
740
741 conn->type = CR_UDPTCPIP;
742 conn->Send = crUDPTCPIPSend;
743 conn->Barf = crUDPTCPIPBarf;
744 conn->SendExact = NULL;
745 conn->Recv = NULL; /* none for UDP : *must* multiplex ! */
746 conn->Accept = crUDPTCPIPAccept;
747 conn->Connect = crUDPTCPIPDoConnect;
748 conn->Disconnect = crUDPTCPIPDoDisconnect;
749 conn->seq = 0;
750 conn->ack = 0;
751 conn->udp_packet = NULL;
752 conn->mtu -= sizeof(conn->seq); /* some room for seq */
753}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette