GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
###########################################################################
##
#W xstream.gi The SCSCP package Alexander Konovalov
#W Steve Linton
##
###########################################################################
###########################################################################
##
## InputOutputTCPStream( <hostname>, <port> )
## InputOutputTCPStream( <socket_descriptor> )
##
## The first usage is to be used by client and specifies hostname and port.
## The second usage is to be used by server and specifies socket descriptor
## which will be used to accept incoming connections.
##
InstallGlobalFunction( InputOutputTCPStream,
function( arg )
# InputOutputLocalProcess has 3 arguments: cdir, exec, argts
# at least for now, we want to preserve four components of the internal
# representation of input/output streams, with the following correspondence
# 1) ptynum --> object in the category IsFile
# 2) basename --> hostname
# 3) argts --> ??? arguments to be communicated to the hostname?
# 4) false --> false # what'is the meaning of this?
local hostname, port, lookup, sock, res, fio, socket_descriptor;
if Length( arg ) = 2 then # client case
hostname := arg[1];
port := arg[2];
if not IsString( hostname ) then
Error( "InputOutputTCPStream: <hostname> must be a string! \n");
fi;
if not ( IsInt(port) and port >= 0 ) then
Error( "InputOutputTCPStream: <port> must be a non-negative integer! \n");
fi;
lookup := IO_gethostbyname( hostname );
if lookup = fail then
Print( "InputOutputTCPStream: cannot find hostname ", hostname, "\n");
return fail;
fi;
Info( InfoSCSCP, 1, "Creating a socket ..." );
sock := IO_socket( IO.PF_INET, IO.SOCK_STREAM, "tcp" );
Info( InfoSCSCP, 1, "Connecting to a remote socket via TCP/IP ..." );
res := IO_connect( sock, IO_make_sockaddr_in( lookup.addr[1], port ) );
if res = fail then
Print( "Error: ", LastSystemError(), "\n" );
IO_close( sock );
return fail;
else
fio := IO_WrapFD( sock, IO.DefaultBufSize, IO.DefaultBufSize );
return Objectify( InputOutputTCPStreamDefaultType,
[ fio, hostname, [ port ], false ] );
fi;
elif Length( arg ) = 1 then # server case
socket_descriptor := arg[1];
if not ( IsInt(socket_descriptor) and socket_descriptor >= 0 ) then
Error( "InputOutputTCPStream: <socket_descriptor> must be a non-negative integer! \n");
fi;
fio := IO_WrapFD( socket_descriptor, IO.DefaultBufSize, IO.DefaultBufSize );
return Objectify( InputOutputTCPStreamDefaultType,
[ fio, "socket descriptor", [ socket_descriptor ], false ] );
else
Error( "InputOutputTCPStream: usage \n",
"InputOutputTCPStream(<hostname>, <port>) for client, \n",
"InputOutputTCPStream(<socket_descriptor>) for server! \n");
fi;
end);
###########################################################################
##
#M ViewObj( <ioTCPstream> )
##
InstallMethod( ViewObj, "for ioTCPstream",
[ IsInputOutputTCPStreamRep and IsInputOutputStream ],
function(stream)
Print("< ");
if IsClosedStream(stream) then
Print("closed ");
fi;
Print("input/output TCP stream to ",stream![2],":", stream![3][1], " >");
end);
###########################################################################
##
#M PrintObj( <ioTCPstream> )
##
InstallMethod( PrintObj, "for ioTCPstream",
[ IsInputOutputTCPStreamRep and IsInputOutputStream ],
function(stream)
local i;
Print("< ");
if IsClosedStream(stream) then
Print("closed ");
fi;
Print("input/output TCP stream to ",stream![2],":", stream![3][1], " >");
end);
###########################################################################
##
#M ReadByte( <ioTCPstream> )
##
InstallMethod( ReadByte, "for ioTCPstream",
[ IsInputOutputTCPStreamRep and IsInputOutputStream ],
function(stream)
local buf;
buf := IO_Read( stream![1], 1 );
if buf = fail or Length(buf) = 0 then
stream![4] := true;
return fail;
else
stream![4] := true;
return INT_CHAR(buf[1]);
fi;
end);
###########################################################################
##
#M ReadLine( <ioTCPstream> )
##
InstallMethod( ReadLine, "for ioTCPstream",
[ IsInputOutputTCPStreamRep and IsInputOutputStream ],
function( stream )
local sofar, chunk;
sofar := IO_Read( stream![1], 1 );
if sofar = fail or Length(sofar) = 0 then
stream![4] := true;
return fail;
fi;
while sofar[ Length(sofar) ] <> '\n' do
chunk := IO_Read( stream![1], 1);
if chunk = fail or Length(chunk) = 0 then
stream![4] := true;
return sofar;
fi;
Append( sofar, chunk );
od;
return sofar;
end);
###########################################################################
##
#M ReadAllIoTCPStream( <ioTCPstream> )
##
BindGlobal( "ReadAllIoTCPStream", function(stream, limit)
local sofar, chunk, csize;
if limit = -1 then
csize := 20000;
else
csize := Minimum(20000,limit);
limit := limit - csize;
fi;
sofar := IO_Read(stream![1], csize);
if sofar = fail or Length(sofar) = 0 then
stream![4] := true;
return fail;
fi;
while limit <> 0 do
if limit = -1 then
csize := 20000;
else
csize := Minimum(20000,limit);
limit := limit - csize;
fi;
chunk := IO_Read( stream![1], csize);
if chunk = fail or Length(chunk) = 0 then
stream![4] := true;
return sofar;
fi;
Append(sofar,chunk);
od;
return sofar;
end);
InstallMethod( ReadAll, "for ioTCPstream",
[ IsInputOutputTCPStreamRep and IsInputOutputStream ],
stream -> ReadAllIoTCPStream(stream, -1) );
InstallMethod( ReadAll, "for ioTCPstream",
[ IsInputOutputTCPStreamRep and IsInputOutputStream, IsInt ],
function( stream, limit )
if limit < 0 then
Error("ReadAll: negative limit not allowed");
fi;
return ReadAllIoTCPStream(stream, limit);
end);
###########################################################################
##
#M WriteByte( <ioTCPstream> )
##
InstallMethod( WriteByte, "for ioTCPstream",
[ IsInputOutputTCPStreamRep and IsInputOutputStream, IsInt ],
function(stream, byte)
local ret,s;
if byte < 0 or 255 < byte then
Error( "<byte> must an integer between 0 and 255" );
fi;
s := [CHAR_INT(byte)];
ConvertToStringRep( s );
ret := IO_Write( stream![1], s );
if ret <> 1 then
return fail;
else
return true;
fi;
end);
###########################################################################
##
#M WriteLine( <ioTCPstream>, <string> ) . . . write plus newline and flush
##
InstallMethod( WriteLine, "for ioTCPstream",
[ IsInputOutputTCPStreamRep and IsInputOutputStream, IsString ],
function( stream, string )
# local res;
# res := WriteAll( stream, string );
# if res <> true then
# return res;
# fi;
# WriteByte( stream, INT_CHAR('\n') );
# return IO_Flush( stream![1] );
return IO_WriteLine( stream![1], string );
end );
###########################################################################
##
#M WriteAll( <ioTCPstream>, <string> ) . . . . . . . . . write all bytes
##
InstallMethod( WriteAll, "for ioTCPstream",
[ IsInputOutputTCPStreamRep and IsInputOutputStream, IsString ],
function( stream, string )
local byte;
for byte in string do
if WriteByte( stream, INT_CHAR(byte) ) <> true then
return fail;
fi;
od;
return true;
end );
###########################################################################
##
#M IsEndOfStream( <ioTCPstream> )
##
InstallMethod( IsEndOfStream, "iostream",
[ IsInputOutputTCPStreamRep and IsInputOutputStream ],
stream -> not IO_HasData( stream![1] ) );
# or IS_BLOCKED_IOSTREAM(stream![1]) );
###########################################################################
##
#M CloseStream( <ioTCPstream> )
##
InstallMethod( CloseStream, "for ioTCPstream",
[ IsInputOutputTCPStreamRep and IsInputOutputStream ],
function(stream)
IO_Close( stream![1] );
SetFilterObj( stream, IsClosedStream );
end);
###########################################################################
##
#M FileDescriptorOfStream( <ioTCPstream> )
##
InstallMethod( FileDescriptorOfStream, "for ioTCPstream",
[ IsInputOutputTCPStreamRep and IsInputOutputStream ],
stream -> IO_GetFD( stream![1] ) );
###########################################################################
##
#F SCSCPwait( <ioTCPstream>, [ <timeout>] )
##
InstallGlobalFunction( SCSCPwait,
function( arg )
if Length(arg) = 2 then
IO_Select( [ arg[1]![1] ], [ ], [ ], [ ], arg[2], 0 );
elif Length(arg) = 1 then
IO_Select( [ arg[1]![1] ], [ ], [ ], [ ], 3600, 0 );
fi;
end);
###########################################################################
##
#E
##