@ -24,6 +24,7 @@
# include "ser-unix.h"
# include "ser-unix.h"
# include <sys/types.h>
# include <sys/types.h>
# include <sys/ioctl.h>
# include <sys/time.h>
# include <sys/time.h>
# include <netinet/in.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <arpa/inet.h>
@ -36,22 +37,23 @@
static int tcp_open ( struct serial * scb , const char * name ) ;
static int tcp_open ( struct serial * scb , const char * name ) ;
static void tcp_close ( struct serial * scb ) ;
static void tcp_close ( struct serial * scb ) ;
extern int ( * ui_loop_hook ) ( int ) ;
void _initialize_ser_tcp ( void ) ;
void _initialize_ser_tcp ( void ) ;
/* Open up a raw tcp socket */
/* seconds to wait for connect */
# define TIMEOUT 15
/* how many times per second to poll ui_loop_hook */
# define POLL_INTERVAL 2
/* Open a tcp socket */
static int
static int
tcp_open ( struct serial * scb , const char * name )
tcp_open ( struct serial * scb , const char * name )
{
{
char * port_str ;
char * port_str , hostname [ 100 ] ;
int port ;
int n , port , tmp ;
struct hostent * hostent ;
struct hostent * hostent ;
struct sockaddr_in sockaddr ;
struct sockaddr_in sockaddr ;
int tmp ;
char hostname [ 100 ] ;
struct protoent * protoent ;
int i ;
port_str = strchr ( name , ' : ' ) ;
port_str = strchr ( name , ' : ' ) ;
@ -63,11 +65,11 @@ tcp_open (struct serial *scb, const char *name)
hostname [ tmp ] = ' \000 ' ; /* Tie off host name */
hostname [ tmp ] = ' \000 ' ; /* Tie off host name */
port = atoi ( port_str + 1 ) ;
port = atoi ( port_str + 1 ) ;
/* default hostname is localhost */
if ( ! hostname [ 0 ] )
if ( ! hostname [ 0 ] )
strcpy ( hostname , " localhost " ) ;
strcpy ( hostname , " localhost " ) ;
hostent = gethostbyname ( hostname ) ;
hostent = gethostbyname ( hostname ) ;
if ( ! hostent )
if ( ! hostent )
{
{
fprintf_unfiltered ( gdb_stderr , " %s: unknown host \n " , hostname ) ;
fprintf_unfiltered ( gdb_stderr , " %s: unknown host \n " , hostname ) ;
@ -75,51 +77,90 @@ tcp_open (struct serial *scb, const char *name)
return - 1 ;
return - 1 ;
}
}
for ( i = 1 ; i < = 15 ; i + + )
{
scb - > fd = socket ( PF_INET , SOCK_STREAM , 0 ) ;
scb - > fd = socket ( PF_INET , SOCK_STREAM , 0 ) ;
if ( scb - > fd < 0 )
if ( scb - > fd < 0 )
return - 1 ;
return - 1 ;
/* Allow rapid reuse of this port. */
tmp = 1 ;
setsockopt ( scb - > fd , SOL_SOCKET , SO_REUSEADDR , ( char * ) & tmp , sizeof ( tmp ) ) ;
/* Enable TCP keep alive process. */
tmp = 1 ;
setsockopt ( scb - > fd , SOL_SOCKET , SO_KEEPALIVE , ( char * ) & tmp , sizeof ( tmp ) ) ;
sockaddr . sin_family = PF_INET ;
sockaddr . sin_family = PF_INET ;
sockaddr . sin_port = htons ( port ) ;
sockaddr . sin_port = htons ( port ) ;
memcpy ( & sockaddr . sin_addr . s_addr , hostent - > h_addr ,
memcpy ( & sockaddr . sin_addr . s_addr , hostent - > h_addr ,
sizeof ( struct in_addr ) ) ;
sizeof ( struct in_addr ) ) ;
if ( ! connect ( scb - > fd , ( struct sockaddr * ) & sockaddr , sizeof ( sockaddr ) ) )
/* set socket nonblocking */
break ;
tmp = 1 ;
ioctl ( scb - > fd , FIONBIO , & tmp ) ;
close ( scb - > fd ) ;
scb - > fd = - 1 ;
/* We retry for ECONNREFUSED because that is often a temporary condition, which
/* Use Non-blocking connect. connect() will return 0 if connected already. */
happens when the server is being restarted . */
n = connect ( scb - > fd , ( struct sockaddr * ) & sockaddr , sizeof ( sockaddr ) ) ;
if ( errno ! = ECONNREFUSED )
if ( n < 0 & & errno ! = EINPROGRESS )
{
tcp_close ( scb ) ;
return - 1 ;
return - 1 ;
}
if ( n )
{
/* looks like we need to wait for the connect */
struct timeval t ;
fd_set rset , wset ;
int polls = 0 ;
FD_ZERO ( & rset ) ;
sleep ( 1 ) ;
do
{
/* While we wait for the connect to complete
poll the UI so it can update or the user can
interrupt . */
if ( ui_loop_hook )
{
if ( ui_loop_hook ( 0 ) )
{
errno = EINTR ;
tcp_close ( scb ) ;
return - 1 ;
}
}
}
FD_SET ( scb - > fd , & rset ) ;
wset = rset ;
t . tv_sec = 0 ;
t . tv_usec = 1000000 / POLL_INTERVAL ;
protoent = getprotobyname ( " tcp " ) ;
n = select ( scb - > fd + 1 , & rset , & wset , NULL , & t ) ;
if ( ! protoent )
polls + + ;
}
while ( n = = 0 & & polls < = TIMEOUT * POLL_INTERVAL ) ;
if ( n < 0 | | polls > TIMEOUT * POLL_INTERVAL )
{
if ( polls > TIMEOUT * POLL_INTERVAL )
errno = ETIMEDOUT ;
tcp_close ( scb ) ;
return - 1 ;
return - 1 ;
}
}
tmp = 1 ;
/* Got something. Is it an error? */
if ( setsockopt ( scb - > fd , protoent - > p_proto , TCP_NODELAY ,
{
( char * ) & tmp , sizeof ( tmp ) ) )
int res , err , len ;
len = sizeof ( err ) ;
res = getsockopt ( scb - > fd , SOL_SOCKET , SO_ERROR , & err , & len ) ;
if ( res < 0 | | err )
{
if ( err )
errno = err ;
tcp_close ( scb ) ;
return - 1 ;
return - 1 ;
}
}
/* turn off nonblocking */
tmp = 0 ;
ioctl ( scb - > fd , FIONBIO , & tmp ) ;
signal ( SIGPIPE , SIG_IGN ) ; /* If we don't do this, then GDB simply exits
/* If we don't do this, then GDB simply exits
when the remote side dies . */
when the remote side dies . */
signal ( SIGPIPE , SIG_IGN ) ;
return 0 ;
return 0 ;
}
}