@ -168,6 +168,11 @@ void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len)
s - > chr_read ( s - > handler_opaque , buf , len ) ;
}
int qemu_chr_get_msgfd ( CharDriverState * s )
{
return s - > get_msgfd ? s - > get_msgfd ( s ) : - 1 ;
}
void qemu_chr_accept_input ( CharDriverState * s )
{
if ( s - > chr_accept_input )
@ -1832,6 +1837,7 @@ typedef struct {
int do_telnetopt ;
int do_nodelay ;
int is_unix ;
int msgfd ;
} TCPCharDriver ;
static void tcp_chr_accept ( void * opaque ) ;
@ -1907,20 +1913,61 @@ static void tcp_chr_process_IAC_bytes(CharDriverState *chr,
* size = j ;
}
static int tcp_get_msgfd ( CharDriverState * chr )
{
TCPCharDriver * s = chr - > opaque ;
return s - > msgfd ;
}
# ifndef WIN32
static void unix_process_msgfd ( CharDriverState * chr , struct msghdr * msg )
{
TCPCharDriver * s = chr - > opaque ;
struct cmsghdr * cmsg ;
for ( cmsg = CMSG_FIRSTHDR ( msg ) ; cmsg ; cmsg = CMSG_NXTHDR ( msg , cmsg ) ) {
int fd ;
if ( cmsg - > cmsg_len ! = CMSG_LEN ( sizeof ( int ) ) | |
cmsg - > cmsg_level ! = SOL_SOCKET | |
cmsg - > cmsg_type ! = SCM_RIGHTS )
continue ;
fd = * ( ( int * ) CMSG_DATA ( cmsg ) ) ;
if ( fd < 0 )
continue ;
if ( s - > msgfd ! = - 1 )
close ( s - > msgfd ) ;
s - > msgfd = fd ;
}
}
static ssize_t tcp_chr_recv ( CharDriverState * chr , char * buf , size_t len )
{
TCPCharDriver * s = chr - > opaque ;
struct msghdr msg = { 0 , } ;
struct iovec iov [ 1 ] ;
union {
struct cmsghdr cmsg ;
char control [ CMSG_SPACE ( sizeof ( int ) ) ] ;
} msg_control ;
ssize_t ret ;
iov [ 0 ] . iov_base = buf ;
iov [ 0 ] . iov_len = len ;
msg . msg_iov = iov ;
msg . msg_iovlen = 1 ;
msg . msg_control = & msg_control ;
msg . msg_controllen = sizeof ( msg_control ) ;
ret = recvmsg ( s - > fd , & msg , 0 ) ;
if ( ret > 0 & & s - > is_unix )
unix_process_msgfd ( chr , & msg ) ;
return recvmsg ( s - > fd , & msg , 0 ) ;
return ret ;
}
# else
static ssize_t tcp_chr_recv ( CharDriverState * chr , char * buf , size_t len )
@ -1957,6 +2004,10 @@ static void tcp_chr_read(void *opaque)
tcp_chr_process_IAC_bytes ( chr , s , buf , & size ) ;
if ( size > 0 )
qemu_chr_read ( chr , buf , size ) ;
if ( s - > msgfd ! = - 1 ) {
close ( s - > msgfd ) ;
s - > msgfd = - 1 ;
}
}
}
@ -2118,12 +2169,14 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
s - > connected = 0 ;
s - > fd = - 1 ;
s - > listen_fd = - 1 ;
s - > msgfd = - 1 ;
s - > is_unix = is_unix ;
s - > do_nodelay = do_nodelay & & ! is_unix ;
chr - > opaque = s ;
chr - > chr_write = tcp_chr_write ;
chr - > chr_close = tcp_chr_close ;
chr - > get_msgfd = tcp_get_msgfd ;
if ( is_listen ) {
s - > listen_fd = fd ;