e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync/* Copyright (c) 2001, Stanford University
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * All rights reserved
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync *
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * See the file LICENSE.txt for information on redistributing this software.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifdef WINDOWS
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#define WIN32_LEAN_AND_MEAN
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#pragma warning( push, 3 )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include <winsock2.h>
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#pragma warning( pop )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#pragma warning( disable : 4514 )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#pragma warning( disable : 4127 )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync# ifndef VBOX
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsynctypedef int ssize_t;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync# endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#else
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include <sys/types.h>
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include <sys/wait.h>
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifdef OSF1
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsynctypedef int socklen_t;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include <sys/socket.h>
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include <sys/time.h>
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include <netinet/in.h>
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include <netinet/tcp.h>
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include <arpa/inet.h>
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include <netdb.h>
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include <unistd.h>
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include <limits.h>
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include <stdlib.h>
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include <stdio.h>
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include <errno.h>
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include <signal.h>
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include <string.h>
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifdef AIX
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include <strings.h>
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifdef LINUX
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include <sys/ioctl.h>
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include <unistd.h>
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include "cr_error.h"
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include "cr_mem.h"
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include "cr_string.h"
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include "cr_bufpool.h"
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include "cr_net.h"
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include "cr_endian.h"
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include "cr_threads.h"
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include "cr_environment.h"
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include "net_internals.h"
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifdef ADDRINFO
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#define PF PF_UNSPEC
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifdef WINDOWS
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#define EADDRINUSE WSAEADDRINUSE
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#define ECONNREFUSED WSAECONNREFUSED
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifdef WINDOWS
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#undef ECONNRESET
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#define ECONNRESET WSAECONNRESET
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#undef EINTR
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#define EINTR WSAEINTR
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncint crTCPIPErrno( void )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return WSAGetLastError( );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncchar *crTCPIPErrorString( int err )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync static char buf[512], *temp;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync sprintf( buf, "err=%d", err );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#define X(x) crStrcpy(buf,x); break
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync switch ( err )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync case WSAECONNREFUSED: X( "connection refused" );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync case WSAECONNRESET: X( "connection reset" );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync default:
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync FORMAT_MESSAGE_FROM_SYSTEM |
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, err,
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync (LPTSTR) &temp, 0, NULL );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( temp )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crStrncpy( buf, temp, sizeof(buf)-1 );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync buf[sizeof(buf)-1] = 0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#undef X
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync temp = buf + crStrlen(buf) - 1;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync while ( temp > buf && isspace( *temp ) )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync *temp = '\0';
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync temp--;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return buf;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#else /* WINDOWS */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncint crTCPIPErrno( void )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int err = errno;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync errno = 0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return err;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncchar *crTCPIPErrorString( int err )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync static char buf[512], *temp;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync temp = strerror( err );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( temp )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crStrncpy( buf, temp, sizeof(buf)-1 );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync buf[sizeof(buf)-1] = 0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync else
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync sprintf( buf, "err=%d", err );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return buf;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif /* WINDOWS */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync/*
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Socket callbacks. When a socket is created or destroyed we will
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * call these callback functions.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * XXX Currently only implemented for TCP/IP.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * XXX Maybe have lists of callbacks?
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncstatic CRSocketCallbackProc SocketCreateCallback = NULL;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncstatic CRSocketCallbackProc SocketDestroyCallback = NULL;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncvoid
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsynccrRegisterSocketCallback(int mode, CRSocketCallbackProc proc)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (mode == CR_SOCKET_CREATE) {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync SocketCreateCallback = proc;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync else if (mode == CR_SOCKET_DESTROY) {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync SocketDestroyCallback = proc;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync else {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crError("Invalid crRegisterSocketCallbac mode=%d", mode);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncvoid crCloseSocket( CRSocket sock )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int fail;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (sock <= 0)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (SocketDestroyCallback) {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync SocketDestroyCallback(CR_SOCKET_DESTROY, sock);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifdef WINDOWS
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync fail = ( closesocket( sock ) != 0 );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#else
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync shutdown( sock, 2 /* RDWR */ );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync fail = ( close( sock ) != 0 );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( fail )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int err = crTCPIPErrno( );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crWarning( "crCloseSocket( sock=%d ): %s",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync sock, crTCPIPErrorString( err ) );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsynccr_tcpip_data cr_tcpip;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync/**
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Read len bytes from socket, and store in buffer.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * \return 1 if success, -1 if error, 0 if sender exited.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncint
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync__tcpip_read_exact( CRSocket sock, void *buf, unsigned int len )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync char *dst = (char *) buf;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /*
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Shouldn't write to a non-existent socket, ie when
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * crTCPIPDoDisconnect has removed it from the pool
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( sock <= 0 )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return 1;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync while ( len > 0 )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync const int num_read = recv( sock, dst, (int) len, 0 );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifdef WINDOWS_XXXX
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* MWE: why is this necessary for windows??? Does it return a
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync "good" value for num_bytes despite having a reset
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync connection? */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( crTCPIPErrno( ) == ECONNRESET )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return -1;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( num_read < 0 )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int error = crTCPIPErrno();
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync switch( error )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync case EINTR:
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crWarning( "__tcpip_read_exact(TCPIP): "
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync "caught an EINTR, looping for more data" );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync continue;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync case EFAULT:
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crWarning( "EFAULT" );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync break;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync case EINVAL:
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crWarning( "EINVAL" );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync break;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync default:
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync break;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crWarning( "Bad bad bad socket error: %s", crTCPIPErrorString( error ) );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return -1;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( num_read == 0 )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* client exited gracefully */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return 0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync dst += num_read;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync len -= num_read;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return 1;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncvoid
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsynccrTCPIPReadExact( CRConnection *conn, void *buf, unsigned int len )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( __tcpip_read_exact( conn->tcp_socket, buf, len ) <= 0 )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync __tcpip_dead_connection( conn );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync/**
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Write the given buffer of len bytes on the socket.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * \return 1 if OK, negative value if error.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncint
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync__tcpip_write_exact( CRSocket sock, const void *buf, unsigned int len )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync const char *src = (const char *) buf;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /*
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Shouldn't write to a non-existent socket, ie when
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * crTCPIPDoDisconnect has removed it from the pool
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( sock <= 0 )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return 1;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync while ( len > 0 )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync const int num_written = send( sock, src, len, 0 );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( num_written <= 0 )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int err;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( (err = crTCPIPErrno( )) == EINTR )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crWarning("__tcpip_write_exact(TCPIP): caught an EINTR, continuing");
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync continue;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return -err;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync len -= num_written;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync src += num_written;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return 1;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncvoid
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsynccrTCPIPWriteExact( CRConnection *conn, const void *buf, unsigned int len )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( __tcpip_write_exact( conn->tcp_socket, buf, len) <= 0 )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync __tcpip_dead_connection( conn );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync/**
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Make sockets do what we want:
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync *
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * 1) Change the size of the send/receive buffers to 64K
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * 2) Turn off Nagle's algorithm
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncstatic void
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncspankSocket( CRSocket sock )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* why do we do 1) ? things work much better for me to push the
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * the buffer size way up -- karl
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifdef LINUX
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int sndbuf = 1*1024*1024;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#else
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int sndbuf = 64*1024;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int rcvbuf = sndbuf;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int so_reuseaddr = 1;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int tcp_nodelay = 1;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( setsockopt( sock, SOL_SOCKET, SO_SNDBUF,
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync (char *) &sndbuf, sizeof(sndbuf) ) )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int err = crTCPIPErrno( );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crWarning( "setsockopt( SO_SNDBUF=%d ) : %s",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync sndbuf, crTCPIPErrorString( err ) );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( setsockopt( sock, SOL_SOCKET, SO_RCVBUF,
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync (char *) &rcvbuf, sizeof(rcvbuf) ) )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int err = crTCPIPErrno( );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crWarning( "setsockopt( SO_RCVBUF=%d ) : %s",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync rcvbuf, crTCPIPErrorString( err ) );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( setsockopt( sock, SOL_SOCKET, SO_REUSEADDR,
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync (char *) &so_reuseaddr, sizeof(so_reuseaddr) ) )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int err = crTCPIPErrno( );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crWarning( "setsockopt( SO_REUSEADDR=%d ) : %s",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync so_reuseaddr, crTCPIPErrorString( err ) );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( setsockopt( sock, IPPROTO_TCP, TCP_NODELAY,
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync (char *) &tcp_nodelay, sizeof(tcp_nodelay) ) )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int err = crTCPIPErrno( );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crWarning( "setsockopt( TCP_NODELAY=%d )"
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync " : %s", tcp_nodelay, crTCPIPErrorString( err ) );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#if defined( WINDOWS ) || defined( IRIX ) || defined( IRIX64 )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsynctypedef int socklen_t;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync/**
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Create a listening socket using the given port.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Caller can then pass the socket to accept().
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * If the port is one that's been seen before, we'll reuse/return the
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * previously create socket.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncstatic int
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncCreateListeningSocket(int port)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* XXX should use an unbounded list here instead of parallel arrays... */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#define MAX_PORTS 100
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync static int ports[MAX_PORTS];
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync static int sockets[MAX_PORTS];
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync static int count = 0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int i, sock = -1;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* search to see if we've seen this port before */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync for (i = 0; i < count; i++) {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (ports[i] == port) {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return sockets[i];
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* new port so create new socket */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int err;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifndef ADDRINFO
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync struct sockaddr_in servaddr;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* with the new OOB stuff, we can have multiple ports being
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * accepted on, so we need to redo the server socket every time.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifndef ADDRINFO
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync sock = socket( AF_INET, SOCK_STREAM, 0 );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( sock == -1 )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync err = crTCPIPErrno( );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crError( "Couldn't create socket: %s", crTCPIPErrorString( err ) );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync spankSocket( sock );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync servaddr.sin_family = AF_INET;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync servaddr.sin_addr.s_addr = INADDR_ANY;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync servaddr.sin_port = htons( (short) port );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( bind( sock, (struct sockaddr *) &servaddr, sizeof(servaddr) ) )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync err = crTCPIPErrno( );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crError( "Couldn't bind to socket (port=%d): %s",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync port, crTCPIPErrorString( err ) );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( listen( sock, 100 /* max pending connections */ ) )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync err = crTCPIPErrno( );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crError( "Couldn't listen on socket: %s", crTCPIPErrorString( err ) );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#else
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync char port_s[NI_MAXSERV];
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync struct addrinfo *res,*cur;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync struct addrinfo hints;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync sprintf(port_s, "%u", (short unsigned) port);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crMemset(&hints, 0, sizeof(hints));
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync hints.ai_flags = AI_PASSIVE;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync hints.ai_family = PF;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync hints.ai_socktype = SOCK_STREAM;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync err = getaddrinfo( NULL, port_s, &hints, &res );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( err )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crError( "Couldn't find local TCP port %s: %s",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync port_s, gai_strerror(err) );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync for (cur=res;cur;cur=cur->ai_next)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync sock = socket( cur->ai_family, cur->ai_socktype, cur->ai_protocol );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( sock == -1 )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync err = crTCPIPErrno( );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (err != EAFNOSUPPORT)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crWarning("Couldn't create socket of family %i: %s, trying another",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync cur->ai_family, crTCPIPErrorString( err ) );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync continue;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync spankSocket( sock );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( bind( sock, cur->ai_addr, cur->ai_addrlen ) )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync err = crTCPIPErrno( );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crWarning( "Couldn't bind to socket (port=%d): %s",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync port, crTCPIPErrorString( err ) );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crCloseSocket( sock );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync continue;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( listen( sock, 100 /* max pending connections */ ) )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync err = crTCPIPErrno( );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crWarning("Couldn't listen on socket: %s", crTCPIPErrorString(err));
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crCloseSocket( sock );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync continue;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync break;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync freeaddrinfo(res);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (!cur)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crError( "Couldn't find/bind local TCP port %s", port_s);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* save the new port/socket */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (count == MAX_PORTS) {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crError("Fatal error in tcpip layer: too many listening ports/sockets");
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync ports[count] = port;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync sockets[count] = sock;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync count++;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return sock;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncvoid
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsynccrTCPIPAccept( CRConnection *conn, const char *hostname, unsigned short port )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int err;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync socklen_t addr_length;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifndef ADDRINFO
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync struct hostent *host;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync struct in_addr sin_addr;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync struct sockaddr addr;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#else
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync struct sockaddr_storage addr;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync char host[NI_MAXHOST];
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync cr_tcpip.server_sock = CreateListeningSocket(port);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* If brokered, we'll contact the mothership to broker the network
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * connection. We'll send the mothership our hostname, the port and
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * our endianness and will get in return a connection ID number.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (conn->broker) {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crError("There shouldn't be any brokered connections in VirtualBox");
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync addr_length = sizeof( addr );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->tcp_socket = accept( cr_tcpip.server_sock, (struct sockaddr *) &addr, &addr_length );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (conn->tcp_socket == -1)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync err = crTCPIPErrno( );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crError( "Couldn't accept client: %s", crTCPIPErrorString( err ) );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (SocketCreateCallback) {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync SocketCreateCallback(CR_SOCKET_CREATE, conn->tcp_socket);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifndef ADDRINFO
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync sin_addr = ((struct sockaddr_in *) &addr)->sin_addr;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync host = gethostbyaddr( (char *) &sin_addr, sizeof( sin_addr), AF_INET );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (host == NULL )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync char *temp = inet_ntoa( sin_addr );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->hostname = crStrdup( temp );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#else
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync err = getnameinfo ( (struct sockaddr *) &addr, addr_length,
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync host, sizeof( host),
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync NULL, 0, NI_NAMEREQD);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( err )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync err = getnameinfo ( (struct sockaddr *) &addr, addr_length,
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync host, sizeof( host),
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync NULL, 0, NI_NUMERICHOST);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( err ) /* shouldn't ever happen */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->hostname = crStrdup("unknown ?!");
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync else
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->hostname = crStrdup( host );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync else
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync char *temp;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifndef ADDRINFO
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->hostname = crStrdup( host->h_name );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#else
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->hostname = crStrdup( host );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync temp = conn->hostname;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync while (*temp && *temp != '.' )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync temp++;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync *temp = '\0';
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifdef RECV_BAIL_OUT
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync err = sizeof(unsigned int);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( getsockopt( conn->tcp_socket, SOL_SOCKET, SO_RCVBUF,
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync (char *) &conn->krecv_buf_size, &err ) )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->krecv_buf_size = 0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crDebug( "Accepted connection from \"%s\".", conn->hostname );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncvoid *
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsynccrTCPIPAlloc( CRConnection *conn )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync CRTCPIPBuffer *buf;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifdef CHROMIUM_THREADSAFE
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crLockMutex(&cr_tcpip.mutex);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync buf = (CRTCPIPBuffer *) crBufferPoolPop( cr_tcpip.bufpool, conn->buffer_size );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( buf == NULL )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crDebug("Buffer pool %p was empty; allocated new %d byte buffer.",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync cr_tcpip.bufpool,
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync (unsigned int)sizeof(CRTCPIPBuffer) + conn->buffer_size);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync buf = (CRTCPIPBuffer *)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crAlloc( sizeof(CRTCPIPBuffer) + conn->buffer_size );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync buf->magic = CR_TCPIP_BUFFER_MAGIC;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync buf->kind = CRTCPIPMemory;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync buf->pad = 0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync buf->allocated = conn->buffer_size;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifdef CHROMIUM_THREADSAFE
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crUnlockMutex(&cr_tcpip.mutex);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return (void *)( buf + 1 );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncstatic void
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsynccrTCPIPSingleRecv( CRConnection *conn, void *buf, unsigned int len )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crTCPIPReadExact( conn, buf, len );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncstatic void
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsynccrTCPIPSend( CRConnection *conn, void **bufp,
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync const void *start, unsigned int len )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( !conn || conn->type == CR_NO_CONNECTION )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (!bufp) {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* We're sending a user-allocated buffer.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Simply write the length & the payload and return.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync const int sendable_len = conn->swap ? SWAP32(len) : len;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crTCPIPWriteExact( conn, &sendable_len, sizeof(len) );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (!conn || conn->type == CR_NO_CONNECTION)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crTCPIPWriteExact( conn, start, len );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync else {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* The region [start .. start + len + 1] lies within a buffer that
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * was allocated with crTCPIPAlloc() and can be put into the free
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * buffer pool when we're done sending it.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync CRTCPIPBuffer *tcpip_buffer;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync unsigned int *lenp;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync tcpip_buffer = (CRTCPIPBuffer *)(*bufp) - 1;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync CRASSERT( tcpip_buffer->magic == CR_TCPIP_BUFFER_MAGIC );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* All of the buffers passed to the send function were allocated
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * with crTCPIPAlloc(), which includes a header with a 4 byte
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * pad field, to insure that we always have a place to write
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * the length field, even when start == *bufp.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync lenp = (unsigned int *) start - 1;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync *lenp = conn->swap ? SWAP32(len) : len;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crTCPIPWriteExact(conn, lenp, len + sizeof(unsigned int));
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Reclaim this pointer for reuse */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifdef CHROMIUM_THREADSAFE
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crLockMutex(&cr_tcpip.mutex);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crBufferPoolPush(cr_tcpip.bufpool, tcpip_buffer, tcpip_buffer->allocated);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifdef CHROMIUM_THREADSAFE
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crUnlockMutex(&cr_tcpip.mutex);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Since the buffer's now in the 'free' buffer pool, the caller can't
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * use it any more. Setting bufp to NULL will make sure the caller
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * doesn't try to re-use the buffer.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync *bufp = NULL;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncvoid
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync__tcpip_dead_connection( CRConnection *conn )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crDebug( "Dead connection (sock=%d, host=%s), removing from pool",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->tcp_socket, conn->hostname );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* remove from connection pool */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crTCPIPDoDisconnect( conn );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncint
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync__crSelect( int n, fd_set *readfds, int sec, int usec )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync for ( ; ; )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int err, num_ready;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (sec || usec)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* We re-init everytime for Linux, as it corrupts
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * the timeout structure, but other OS's
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * don't have a problem with it.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync struct timeval timeout;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync timeout.tv_sec = sec;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync timeout.tv_usec = usec;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync num_ready = select( n, readfds, NULL, NULL, &timeout );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync else
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync num_ready = select( n, readfds, NULL, NULL, NULL );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( num_ready >= 0 )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return num_ready;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync err = crTCPIPErrno( );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( err == EINTR )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
d72aa6b0dab3e9b60aa78bfca99c767c48a406b0vboxsync crWarning( "select interrupted by an unblocked signal, trying again" );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync else
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crError( "select failed: %s", crTCPIPErrorString( err ) );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncvoid
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsynccrTCPIPFree( CRConnection *conn, void *buf )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync CRTCPIPBuffer *tcpip_buffer = (CRTCPIPBuffer *) buf - 1;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync CRASSERT( tcpip_buffer->magic == CR_TCPIP_BUFFER_MAGIC );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->recv_credits += tcpip_buffer->len;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync switch ( tcpip_buffer->kind )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync case CRTCPIPMemory:
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifdef CHROMIUM_THREADSAFE
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crLockMutex(&cr_tcpip.mutex);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (cr_tcpip.bufpool) {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* pool may have been deallocated just a bit earlier in response
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * to a SIGPIPE (Broken Pipe) signal.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crBufferPoolPush( cr_tcpip.bufpool, tcpip_buffer, tcpip_buffer->allocated );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifdef CHROMIUM_THREADSAFE
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crUnlockMutex(&cr_tcpip.mutex);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync break;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync case CRTCPIPMemoryBig:
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crFree( tcpip_buffer );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync break;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync default:
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crError( "Weird buffer kind trying to free in crTCPIPFree: %d", tcpip_buffer->kind );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync/**
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Check if message type is GATHER. If so, process it specially.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * \return number of bytes which were consumed
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncstatic int
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsynccrTCPIPUserbufRecv(CRConnection *conn, CRMessage *msg)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (msg->header.type == CR_MESSAGE_GATHER) {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* grab the offset and the length */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync const int len = 2 * sizeof(unsigned int); /* was unsigned long!!!! */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync unsigned int buf[2];
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (__tcpip_read_exact(conn->tcp_socket, buf, len) <= 0)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync __tcpip_dead_connection( conn );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync msg->gather.offset = buf[0];
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync msg->gather.len = buf[1];
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* read the rest into the userbuf */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (buf[0] + buf[1] > (unsigned int) conn->userbuf_len)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crDebug("userbuf for Gather Message is too small!");
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return len;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (__tcpip_read_exact(conn->tcp_socket,
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->userbuf + buf[0], buf[1]) <= 0)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync __tcpip_dead_connection( conn );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return len + buf[1];
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync else {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return 0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync/**
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Receive the next message on the given connection.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * If we're being called by crTCPIPRecv(), we already know there's
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * something to receive.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncstatic void
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsynccrTCPIPReceiveMessage(CRConnection *conn)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync CRMessage *msg;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync CRMessageType cached_type;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync CRTCPIPBuffer *tcpip_buffer;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync unsigned int len, total, leftover;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync const int sock = conn->tcp_socket;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Our gigE board is acting odd. If we recv() an amount
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * less than what is already in the RECVBUF, performance
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * goes into the toilet (somewhere around a factor of 3).
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * This is an ugly hack, but seems to get around whatever
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * funk is being produced
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync *
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Remember to set your kernel recv buffers to be bigger
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * than the framebuffer 'chunk' you are sending (see
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * sysctl -a | grep rmem) , or this will really have no
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * effect. --karl
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifdef RECV_BAIL_OUT
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int inbuf;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync (void) recv(sock, &len, sizeof(len), MSG_PEEK);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync ioctl(conn->tcp_socket, FIONREAD, &inbuf);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ((conn->krecv_buf_size > len) && (inbuf < len))
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* this reads the length of the message */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( __tcpip_read_exact( sock, &len, sizeof(len)) <= 0 )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync __tcpip_dead_connection( conn );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (conn->swap)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync len = SWAP32(len);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync CRASSERT( len > 0 );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( len <= conn->buffer_size )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* put in pre-allocated buffer */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync tcpip_buffer = (CRTCPIPBuffer *) crTCPIPAlloc( conn ) - 1;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync else
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* allocate new buffer */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync tcpip_buffer = (CRTCPIPBuffer *) crAlloc( sizeof(*tcpip_buffer) + len );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync tcpip_buffer->magic = CR_TCPIP_BUFFER_MAGIC;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync tcpip_buffer->kind = CRTCPIPMemoryBig;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync tcpip_buffer->pad = 0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync tcpip_buffer->len = len;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* if we have set a userbuf, and there is room in it, we probably
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * want to stick the message into that, instead of our allocated
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * buffer.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync leftover = 0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync total = len;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ((conn->userbuf != NULL)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync && (conn->userbuf_len >= (int) sizeof(CRMessageHeader)))
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync leftover = len - sizeof(CRMessageHeader);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync total = sizeof(CRMessageHeader);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( __tcpip_read_exact( sock, tcpip_buffer + 1, total) <= 0 )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crWarning( "Bad juju: %d %d on socket 0x%x", tcpip_buffer->allocated,
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync total, sock );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crFree( tcpip_buffer );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync __tcpip_dead_connection( conn );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->recv_credits -= total;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->total_bytes_recv += total;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync msg = (CRMessage *) (tcpip_buffer + 1);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync cached_type = msg->header.type;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (conn->swap)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync msg->header.type = (CRMessageType) SWAP32( msg->header.type );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync msg->header.conn_id = (CRMessageType) SWAP32( msg->header.conn_id );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* if there is still data pending, it should go into the user buffer */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (leftover)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync const unsigned int handled = crTCPIPUserbufRecv(conn, msg);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* if there is anything left, plop it into the recv_buffer */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (leftover - handled)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( __tcpip_read_exact( sock, tcpip_buffer + 1 + total, leftover-handled) <= 0 )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crWarning( "Bad juju: %d %d", tcpip_buffer->allocated, leftover-handled);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crFree( tcpip_buffer );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync __tcpip_dead_connection( conn );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->recv_credits -= handled;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->total_bytes_recv += handled;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crNetDispatchMessage( cr_tcpip.recv_list, conn, msg, len );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#if 0
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crLogRead( len );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* CR_MESSAGE_OPCODES is freed in crserverlib/server_stream.c with crNetFree.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * OOB messages are the programmer's problem. -- Humper 12/17/01
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (cached_type != CR_MESSAGE_OPCODES
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync && cached_type != CR_MESSAGE_OOB
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync && cached_type != CR_MESSAGE_GATHER)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crTCPIPFree( conn, tcpip_buffer + 1 );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync/**
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Loop over all TCP/IP connections, reading incoming data on those
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * that are ready.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncint
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsynccrTCPIPRecv( void )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* ensure we don't get caught with a new thread connecting */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync const int num_conns = cr_tcpip.num_conns;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int num_ready, max_fd, i;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync fd_set read_fds;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int msock = -1; /* assumed mothership socket */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#if CRAPPFAKER_SHOULD_DIE
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int none_left = 1;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifdef CHROMIUM_THREADSAFE
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crLockMutex(&cr_tcpip.recvmutex);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /*
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Loop over all connections and determine which are TCP/IP connections
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * that are ready to be read.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync max_fd = 0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync FD_ZERO( &read_fds );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync for ( i = 0; i < num_conns; i++ )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync CRConnection *conn = cr_tcpip.conns[i];
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( !conn || conn->type == CR_NO_CONNECTION )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync continue;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#if CRAPPFAKER_SHOULD_DIE
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync none_left = 0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( conn->recv_credits > 0 || conn->type != CR_TCPIP )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /*
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * NOTE: may want to always put the FD in the descriptor
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * set so we'll notice broken connections. Down in the
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * loop that iterates over the ready sockets only peek
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * (MSG_PEEK flag to recv()?) if the connection isn't
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * enabled.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#if 0 /* not used - see below */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifndef ADDRINFO
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync struct sockaddr s;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#else
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync struct sockaddr_storage s;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync socklen_t slen;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync fd_set only_fd; /* testing single fd */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync CRSocket sock = conn->tcp_socket;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( (int) sock + 1 > max_fd )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync max_fd = (int) sock + 1;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync FD_SET( sock, &read_fds );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* KLUDGE CITY......
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync *
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * With threads there's a race condition between
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * TCPIPRecv and TCPIPSingleRecv when new
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * clients are connecting, thus new mothership
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * connections are also being established.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * This code below is to check that we're not
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * in a state of accepting the socket without
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * connecting to it otherwise we fail with
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * ENOTCONN later. But, this is really a side
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * effect of this routine catching a motherships
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * socket connection and reading data that wasn't
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * really meant for us. It was really meant for
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * TCPIPSingleRecv. So, if we detect an
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * in-progress connection we set the msock id
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * so that we can assume the motherships socket
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * and skip over them.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync FD_ZERO(&only_fd);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync FD_SET( sock, &only_fd );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#if 0 /* Disabled on Dec 13 2005 by BrianP - seems to cause trouble */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync slen = sizeof( s );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Check that the socket is REALLY connected */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Doesn't this call introduce some inefficiency??? (BP) */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (getpeername(sock, (struct sockaddr *) &s, &slen) < 0) {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Another kludge.....
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * If we disconnect a socket without writing
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * anything to it, we end up here. Detect
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * the disconnected socket by checking if
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * we've ever sent something and then
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * disconnect it.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync *
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * I think the networking layer needs
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * a bit of a re-write.... Alan.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (conn->total_bytes_sent > 0) {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crTCPIPDoDisconnect( conn );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync FD_CLR(sock, &read_fds);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync msock = sock;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /*
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Nope, that last socket we've just caught in
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * the connecting phase. We've probably found
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * a mothership connection here, and we shouldn't
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * process it
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ((int)sock == msock+1)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync FD_CLR(sock, &read_fds);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#if CRAPPFAKER_SHOULD_DIE
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (none_left) {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /*
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Caught no more connections.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Review this if we want to try
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * restarting crserver's dynamically.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifdef CHROMIUM_THREADSAFE
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crUnlockMutex(&cr_tcpip.recvmutex);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crError("No more connections to process, terminating...\n");
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync exit(0); /* shouldn't get here */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (!max_fd) {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifdef CHROMIUM_THREADSAFE
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crUnlockMutex(&cr_tcpip.recvmutex);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return 0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( num_conns ) {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync num_ready = __crSelect( max_fd, &read_fds, 0, 500 );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync else {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crWarning( "Waiting for first connection..." );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync num_ready = __crSelect( max_fd, &read_fds, 0, 0 );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( num_ready == 0 ) {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifdef CHROMIUM_THREADSAFE
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crUnlockMutex(&cr_tcpip.recvmutex);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return 0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /*
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Loop over connections, receive data on the TCP/IP connections that
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * we determined are ready above.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync for ( i = 0; i < num_conns; i++ )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync CRConnection *conn = cr_tcpip.conns[i];
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync CRSocket sock;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( !conn || conn->type == CR_NO_CONNECTION )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync continue;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Added by Samuel Thibault during TCP/IP / UDP code factorization */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( conn->type != CR_TCPIP )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync continue;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync sock = conn->tcp_socket;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( !FD_ISSET( sock, &read_fds ) )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync continue;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (conn->threaded)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync continue;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crTCPIPReceiveMessage(conn);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifdef CHROMIUM_THREADSAFE
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crUnlockMutex(&cr_tcpip.recvmutex);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return 1;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncstatic void
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsynccrTCPIPHandleNewMessage( CRConnection *conn, CRMessage *msg, unsigned int len )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync CRTCPIPBuffer *buf = ((CRTCPIPBuffer *) msg) - 1;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* build a header so we can delete the message later */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync buf->magic = CR_TCPIP_BUFFER_MAGIC;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync buf->kind = CRTCPIPMemory;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync buf->len = len;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync buf->pad = 0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crNetDispatchMessage( cr_tcpip.recv_list, conn, msg, len );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncstatic void
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsynccrTCPIPInstantReclaim( CRConnection *conn, CRMessage *mess )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crTCPIPFree( conn, mess );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncvoid
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsynccrTCPIPInit( CRNetReceiveFuncList *rfl, CRNetCloseFuncList *cfl,
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync unsigned int mtu )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync (void) mtu;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync cr_tcpip.recv_list = rfl;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync cr_tcpip.close_list = cfl;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( cr_tcpip.initialized )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync cr_tcpip.initialized = 1;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync cr_tcpip.num_conns = 0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync cr_tcpip.conns = NULL;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync cr_tcpip.server_sock = -1;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifdef CHROMIUM_THREADSAFE
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crInitMutex(&cr_tcpip.mutex);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crInitMutex(&cr_tcpip.recvmutex);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync cr_tcpip.bufpool = crBufferPoolInit(16);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync/**
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * The function that actually connects. This should only be called by clients
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Servers have another way to set up the socket.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncint
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsynccrTCPIPDoConnect( CRConnection *conn )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int err;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifndef ADDRINFO
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync struct sockaddr_in servaddr;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync struct hostent *hp;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int i;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->tcp_socket = socket( AF_INET, SOCK_STREAM, 0 );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( conn->tcp_socket < 0 )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int err = crTCPIPErrno( );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crWarning( "socket error: %s", crTCPIPErrorString( err ) );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync cr_tcpip.conns[conn->index] = NULL; /* remove from table */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return 0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (SocketCreateCallback) {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync SocketCreateCallback(CR_SOCKET_CREATE, conn->tcp_socket);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Set up the socket the way *we* want. */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync spankSocket( conn->tcp_socket );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Standard Berkeley sockets mumbo jumbo */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync hp = gethostbyname( conn->hostname );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( !hp )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crWarning( "Unknown host: \"%s\"", conn->hostname );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync cr_tcpip.conns[conn->index] = NULL; /* remove from table */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return 0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crMemset( &servaddr, 0, sizeof(servaddr) );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync servaddr.sin_family = AF_INET;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync servaddr.sin_port = htons( (short) conn->port );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crMemcpy((char *) &servaddr.sin_addr, hp->h_addr, sizeof(servaddr.sin_addr));
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#else
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync char port_s[NI_MAXSERV];
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync struct addrinfo *res,*cur;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync struct addrinfo hints;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync sprintf(port_s, "%u", (short unsigned) conn->port);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crMemset(&hints, 0, sizeof(hints));
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync hints.ai_family = PF;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync hints.ai_socktype = SOCK_STREAM;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync err = getaddrinfo( conn->hostname, port_s, &hints, &res);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( err )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crWarning( "Unknown host: \"%s\": %s", conn->hostname, gai_strerror(err) );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync cr_tcpip.conns[conn->index] = NULL; /* remove from table */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return 0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* If brokered, we'll contact the mothership to broker the network
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * connection. We'll send the mothership our hostname, the port and
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * our endianness and will get in return a connection ID number.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (conn->broker)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crError("There shouldn't be any brokered connections in VirtualBox");
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifndef ADDRINFO
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync for (i=1;i;)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#else
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync for (cur=res;cur;)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifndef ADDRINFO
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifdef RECV_BAIL_OUT
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync err = sizeof(unsigned int);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( getsockopt( conn->tcp_socket, SOL_SOCKET, SO_RCVBUF,
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync (char *) &conn->krecv_buf_size, &err ) )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->krecv_buf_size = 0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( !connect( conn->tcp_socket, (struct sockaddr *) &servaddr,
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync sizeof(servaddr) ) )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return 1;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#else
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->tcp_socket = socket( cur->ai_family, cur->ai_socktype, cur->ai_protocol );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( conn->tcp_socket < 0 )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int err = crTCPIPErrno( );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (err != EAFNOSUPPORT)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crWarning( "socket error: %s, trying another way", crTCPIPErrorString( err ) );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync cur=cur->ai_next;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync continue;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (SocketCreateCallback) {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync SocketCreateCallback(CR_SOCKET_CREATE, conn->tcp_socket);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync err = 1;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync setsockopt(conn->tcp_socket, SOL_SOCKET, SO_REUSEADDR, &err, sizeof(int));
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Set up the socket the way *we* want. */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync spankSocket( conn->tcp_socket );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#if RECV_BAIL_OUT
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync err = sizeof(unsigned int);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( getsockopt( conn->tcp_socket, SOL_SOCKET, SO_RCVBUF,
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync (char *) &conn->krecv_buf_size, &err ) )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->krecv_buf_size = 0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( !connect( conn->tcp_socket, cur->ai_addr, cur->ai_addrlen ) ) {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync freeaddrinfo(res);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return 1;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync err = crTCPIPErrno( );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( err == EADDRINUSE || err == ECONNREFUSED )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crWarning( "Connection refused to %s:%d, %s",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->hostname, conn->port, crTCPIPErrorString( err ) );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync else if ( err == EINTR )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crWarning( "connection to %s:%d "
d72aa6b0dab3e9b60aa78bfca99c767c48a406b0vboxsync "interrupted, trying again", conn->hostname, conn->port );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync continue;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync else
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crWarning( "Couldn't connect to %s:%d, %s",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->hostname, conn->port, crTCPIPErrorString( err ) );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crCloseSocket( conn->tcp_socket );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifndef ADDRINFO
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync i=0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#else
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync cur=cur->ai_next;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifdef ADDRINFO
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync freeaddrinfo(res);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crWarning( "Couldn't find any suitable way to connect to %s", conn->hostname );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync cr_tcpip.conns[conn->index] = NULL; /* remove from table */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return 0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync/**
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Disconnect this connection, but don't free(conn).
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncvoid
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsynccrTCPIPDoDisconnect( CRConnection *conn )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int num_conns = cr_tcpip.num_conns;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int none_left = 1;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int i;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* If this connection has already been disconnected (e.g.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * if the connection has been lost and disabled through
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * a call to __tcpip_dead_connection(), which will then
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * call this routine), don't disconnect it again; if we
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * do, and if a new valid connection appears in the same
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * slot (conn->index), we'll effectively disable the
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * valid connection by mistake, leaving us unable to
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * receive inbound data on that connection.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (conn->type == CR_NO_CONNECTION) return;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crCloseSocket( conn->tcp_socket );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (conn->hostname) {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crFree(conn->hostname);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->hostname = NULL;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->tcp_socket = 0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->type = CR_NO_CONNECTION;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync cr_tcpip.conns[conn->index] = NULL;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* see if any connections remain */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync for (i = 0; i < num_conns; i++)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( cr_tcpip.conns[i] && cr_tcpip.conns[i]->type != CR_NO_CONNECTION )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync none_left = 0; /* found a live connection */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#if 0 /* disabled on 13 Dec 2005 by BrianP - this prevents future client
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * connections after the last one goes away.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (none_left && cr_tcpip.server_sock != -1)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crDebug("Closing master socket (probably quitting).");
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crCloseSocket( cr_tcpip.server_sock );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync cr_tcpip.server_sock = -1;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#ifdef CHROMIUM_THREADSAFE
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crFreeMutex(&cr_tcpip.mutex);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crFreeMutex(&cr_tcpip.recvmutex);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crBufferPoolFree( cr_tcpip.bufpool );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync cr_tcpip.bufpool = NULL;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync last_port = 0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync cr_tcpip.initialized = 0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync/**
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Initialize a CRConnection for tcp/ip. This is called via the
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * InitConnection() function (and from the UDP module).
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncvoid
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsynccrTCPIPConnection( CRConnection *conn )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int i, found = 0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int n_bytes;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync CRASSERT( cr_tcpip.initialized );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->type = CR_TCPIP;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->Alloc = crTCPIPAlloc;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->Send = crTCPIPSend;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->SendExact = crTCPIPWriteExact;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->Recv = crTCPIPSingleRecv;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->RecvMsg = crTCPIPReceiveMessage;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->Free = crTCPIPFree;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->Accept = crTCPIPAccept;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->Connect = crTCPIPDoConnect;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->Disconnect = crTCPIPDoDisconnect;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->InstantReclaim = crTCPIPInstantReclaim;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->HandleNewMessage = crTCPIPHandleNewMessage;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->index = cr_tcpip.num_conns;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->sizeof_buffer_header = sizeof( CRTCPIPBuffer );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->actual_network = 1;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->krecv_buf_size = 0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Find a free slot */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync for (i = 0; i < cr_tcpip.num_conns; i++) {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (cr_tcpip.conns[i] == NULL) {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync conn->index = i;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync cr_tcpip.conns[i] = conn;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync found = 1;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync break;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Realloc connection stack if we couldn't find a free slot */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (found == 0) {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync n_bytes = ( cr_tcpip.num_conns + 1 ) * sizeof(*cr_tcpip.conns);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crRealloc( (void **) &cr_tcpip.conns, n_bytes );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync cr_tcpip.conns[cr_tcpip.num_conns++] = conn;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncint crGetHostname( char *buf, unsigned int len )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync const char *override;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int ret;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync override = crGetenv("CR_HOSTNAME");
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (override)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync crStrncpy(buf, override, len);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync ret = 0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync else
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync ret = gethostname( buf, len );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return ret;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncCRConnection** crTCPIPDump( int *num )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync *num = cr_tcpip.num_conns;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return cr_tcpip.conns;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}