123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508 |
- {
- This file is part of the Free Pascal run time library.
- Copyright (c) 1999-2000 by the Free Pascal development team
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- {******************************************************************************
- Text File Writeln/ReadLn Support
- ******************************************************************************}
- Procedure OpenSock(var F:Text);
- begin
- if textrec(f).handle=UnusedHandle then
- textrec(f).mode:=fmclosed
- else
- case textrec(f).userdata[1] of
- S_OUT : textrec(f).mode:=fmoutput;
- S_IN : textrec(f).mode:=fminput;
- else
- textrec(f).mode:=fmclosed;
- end;
- end;
- procedure iosock(var f:text);
- var r:sizeint;
- def_error:word;
- begin
- with textrec(f) do
- begin
- case mode of
- fmoutput:
- begin
- repeat
- {$ifdef use_readwrite}
- r:=fpwrite(handle,bufptr^,bufpos);
- {$else}
- r:=fpsend(handle,bufptr,bufpos,0);
- {$endif}
- until (r<>-1) or (SocketError <> EsockEINTR);
- bufend:=r;
- def_error:=101; {File write error.}
- end;
- fminput:
- begin
- repeat
- {$ifdef use_readwrite}
- r:=fpread(handle,bufptr^,bufsize);
- {$else}
- r:=fprecv(handle,bufptr,bufsize,0);
- {$endif}
- until (r<>-1) or (SocketError <> EsockEINTR);
- bufend:=r;
- def_error:=100; {File read error.}
- end;
- end;
- if r=-1 then
- case SocketError of
- EsockEBADF:
- { EsysENOTSOCK:} {Why is this constant not defined? (DM)}
- inoutres:=6; {Invalid file handle.}
- EsockEFAULT:
- inoutres:=217;
- EsockEINVAL:
- inoutres:=218;
- else
- inoutres:=def_error;
- end;
- bufpos:=0;
- end;
- end;
- Procedure FlushSock(var F:Text);
- begin
- if (textrec(f).mode=fmoutput) and (textrec(f).bufpos<>0) then
- begin
- IOSock(f);
- textrec(f).bufpos:=0;
- end;
- end;
- Procedure CloseSock(var F:text);
- begin
- { Nothing special has to be done here }
- end;
- Procedure Sock2Text(Sock:Longint;Var SockIn,SockOut:Text);
- {
- Set up two Pascal Text file descriptors for reading and writing)
- }
- begin
- { First the reading part.}
- Assign(SockIn,'.');
- Textrec(SockIn).Handle:=Sock;
- Textrec(Sockin).userdata[1]:=S_IN;
- TextRec(SockIn).OpenFunc:=@OpenSock;
- TextRec(SockIn).InOutFunc:=@IOSock;
- TextRec(SockIn).FlushFunc:=@FlushSock;
- TextRec(SockIn).CloseFunc:=@CloseSock;
- TextRec(SockIn).Mode := fmInput;
- Case DefaultTextLineBreakStyle Of
- tlbsLF: TextRec(sockin).LineEnd := #10;
- tlbsCRLF: TextRec(sockin).LineEnd := #13#10;
- tlbsCR: TextRec(sockin).LineEnd := #13;
- End;
- { Now the writing part. }
- Assign(SockOut,'.');
- Textrec(SockOut).Handle:=Sock;
- Textrec(SockOut).userdata[1]:=S_OUT;
- TextRec(SockOut).OpenFunc:=@OpenSock;
- TextRec(SockOut).InOutFunc:=@IOSock;
- TextRec(SockOut).FlushFunc:=@FlushSock;
- TextRec(SockOut).CloseFunc:=@CloseSock;
- TextRec(SockOut).Mode := fmOutput;
- Case DefaultTextLineBreakStyle Of
- tlbsLF: TextRec(sockout).LineEnd := #10;
- tlbsCRLF: TextRec(sockout).LineEnd := #13#10;
- tlbsCR: TextRec(sockout).LineEnd := #13;
- End;
- end;
- {******************************************************************************
- Untyped File
- ******************************************************************************}
- Procedure Sock2File(Sock:Longint;Var SockIn,SockOut:File);
- begin
- {Input}
- Assign(SockIn,'.');
- FileRec(SockIn).Handle:=Sock;
- FileRec(SockIn).RecSize:=1;
- FileRec(Sockin).userdata[1]:=S_IN;
- FileRec(SockIn).Mode := fmInput;
- {Output}
- Assign(SockOut,'.');
- FileRec(SockOut).Handle:=Sock;
- FileRec(SockOut).RecSize:=1;
- FileRec(SockOut).userdata[1]:=S_OUT;
- FileRec(SockOut).Mode := fmOutput;
- end;
- {******************************************************************************
- InetSock
- ******************************************************************************}
- Function DoAccept(Sock:longint;Var addr:TInetSockAddr):longint;
- Var AddrLen : Longint;
- begin
- AddrLEn:=SizeOf(Addr);
- repeat
- DoAccept:=fpaccept(Sock,@Addr,@AddrLen);
- until (DoAccept<>-1) or (SocketError <> EsockEINTR);
- end;
- Function DoConnect(Sock:longint;const addr: TInetSockAddr): Boolean;
- var
- res: longint;
- begin
- repeat
- res:=fpconnect(Sock,@Addr,SizeOF(TInetSockAddr));
- until (res<>-1) or (SocketError <> EsockEINTR);
- DoConnect:= res = 0;
- end;
- {$warnings off}
- Function Connect(Sock:longint;const addr: TInetSockAddr;var SockIn,SockOut:text):Boolean;
- begin
- Connect:=DoConnect(Sock,addr);
- If Connect then
- Sock2Text(Sock,SockIn,SockOut);
- end;
- Function Connect(Sock:longint;const addr:TInetSockAddr;var SockIn,SockOut:file):Boolean;
- begin
- Connect:=DoConnect(Sock,addr);
- If Connect then
- Sock2File(Sock,SockIn,SockOut);
- end;
- Function Accept(Sock:longint;var addr:TInetSockAddr;var SockIn,SockOut:text):Boolean;
- var
- s : longint;
- begin
- S:=DoAccept(Sock,addr);
- if S>0 then
- begin
- Sock2Text(S,SockIn,SockOut);
- Accept:=true;
- end
- else
- Accept:=false;
- end;
- Function Accept(Sock:longint;var addr:TInetSockAddr;var SockIn,SockOut:File):Boolean;
- var
- s : longint;
- begin
- S:=DoAccept(Sock,addr);
- if S>0 then
- begin
- Sock2File(S,SockIn,SockOut);
- Accept:=true;
- end
- else
- Accept:=false;
- end;
- {$warnings on}
- type thostaddr= packed array[1..4] of byte;
- function htonl( host : longint):longint; inline;
- begin
- {$ifdef FPC_BIG_ENDIAN}
- htonl:=host;
- {$else}
- htonl:=THostAddr(host)[4];
- htonl:=htonl or longint( (THostAddr(host)[3]) shl 8);
- htonl:=htonl or longint( (THostAddr(host)[2]) shl 16);
- htonl:=htonl or longint( (THostAddr(host)[1]) shl 24);
- {$endif}
- end;
- Function NToHl (Net : Longint) : Longint; inline;
- begin
- {$ifdef FPC_BIG_ENDIAN}
- ntohl:=net;
- {$else}
- ntohl:=THostAddr(Net)[4];
- ntohl:=ntohl or longint( (THostAddr(Net)[3]) shl 8);
- ntohl:=ntohl or longint( (THostAddr(Net)[2]) shl 16);
- ntohl:=ntohl or longint( (THostAddr(Net)[1]) shl 24);
- {$endif}
- end;
- function htons( host : word):word; inline;
- begin
- {$ifdef FPC_BIG_ENDIAN}
- htons:=host;
- {$else}
- htons:=swap(host);
- {$endif}
- end;
- Function NToHs (Net : word):word; inline;
- begin
- {$ifdef FPC_BIG_ENDIAN}
- ntohs:=net;
- {$else}
- ntohs:=swap(net);
- {$endif}
- end;
- Type array4int = array[1..4] of byte;
- function NetAddrToStr (Entry : in_addr) : AnsiString;
- Var Dummy : Ansistring;
- i,j : Longint;
- begin
- NetAddrToStr:='';
- j:=entry.s_addr;
- For I:=1 to 4 do
- begin
- Str(array4int(j)[i],Dummy);
- NetAddrToStr:=NetAddrToStr+Dummy;
- If I<4 Then
- NetAddrToStr:=NetAddrToStr+'.';
- end;
- end;
- function HostAddrToStr (Entry : in_addr) : AnsiString;
- Var x: in_addr;
- begin
- x.s_addr:=htonl(entry.s_addr);
- HostAddrToStr:=NetAddrToStr(x);
- end;
- function StrToHostAddr(IP : AnsiString) : in_addr ;
- Var
- Dummy : AnsiString;
- I,j,k : Longint;
- Temp : in_addr;
- begin
- strtohostaddr.s_addr:=0; //:=NoAddress;
- For I:=1 to 4 do
- begin
- If I<4 Then
- begin
- J:=Pos('.',IP);
- If J=0 then
- exit;
- Dummy:=Copy(IP,1,J-1);
- Delete (IP,1,J);
- end
- else
- Dummy:=IP;
- Val (Dummy,k,J);
- array4int(temp.s_addr)[i]:=k;
- If J<>0 then Exit;
- end;
- strtohostaddr.s_addr:=ntohl(Temp.s_addr);
- end;
- function StrToNetAddr(IP : AnsiString) : in_addr;
- begin
- StrToNetAddr.s_addr:=htonl(StrToHostAddr(IP).s_addr);
- end;
- Function HostToNet (Host : in_addr):in_addr;
- begin
- HostToNet.s_addr:=htonl(host.s_addr);
- end;
- Function NetToHost (Net : in_addr) : in_addr;
- begin
- NetToHost.s_addr:=ntohl(net.s_addr);
- end;
- Function HostToNet (Host : Longint) : Longint;
- begin
- HostToNet:=htonl(host);
- end;
- Function NetToHost (Net : Longint) : Longint;
- begin
- NetToHost:=ntohl(net);
- end;
- Function ShortHostToNet (Host : Word) : Word;
- begin
- ShortHostToNet:=htons(host);
- end;
- Function ShortNetToHost (Net : Word) : Word;
- begin
- ShortNEtToHost:=ntohs(net);
- end;
- const digittab : shortstring = ('0123456789ABCDEF');
- function lclinttohex (i:integer;digits:longint): ansistring;
- begin
- SetLength(lclinttohex,4);
- lclinttohex[4]:=digittab[1+(i and 15)];
- lclinttohex[3]:=digittab[1+((i shr 4) and 15)];
- lclinttohex[2]:=digittab[1+((i shr 8) and 15)];
- lclinttohex[1]:=digittab[1+((i shr 12) and 15)];;
- end;
- function HostAddrToStr6 (Entry : TIn6_Addr) :ansiString;
- var
- i: byte;
- zr1,zr2: set of byte;
- zc1,zc2: byte;
- have_skipped: boolean;
- begin
- zr1 := [];
- zr2 := [];
- zc1 := 0;
- zc2 := 0;
- for i := 0 to 7 do begin
- if Entry.u6_addr16[i] = 0 then begin
- include(zr2, i);
- inc(zc2);
- end else begin
- if zc1 < zc2 then begin
- zc1 := zc2;
- zr1 := zr2;
- zc2 := 0; zr2 := [];
- end;
- end;
- end;
- if zc1 < zc2 then begin
- zc1 := zc2;
- zr1 := zr2;
- end;
- SetLength(HostAddrToStr6, 8*5-1);
- SetLength(HostAddrToStr6, 0);
- have_skipped := false;
- for i := 0 to 7 do begin
- if not (i in zr1) then begin
- if have_skipped then begin
- if HostAddrToStr6 = ''
- then HostAddrToStr6 := '::'
- else HostAddrToStr6 := HostAddrToStr6 + ':';
- have_skipped := false;
- end;
- // FIXME: is that shortnettohost really proper there? I wouldn't be too sure...
- HostAddrToStr6 := HostAddrToStr6 +lclIntToHex(ShortNetToHost(Entry.u6_addr16[i]), 1) + ':';
- end else begin
- have_skipped := true;
- end;
- end;
- if have_skipped then
- if HostAddrToStr6 = ''
- then HostAddrToStr6 := '::'
- else HostAddrToStr6 := HostAddrToStr6 + ':';
- if HostAddrToStr6 = '' then HostAddrToStr6 := '::';
- if not (7 in zr1) then
- SetLength(HostAddrToStr6, Length(HostAddrToStr6)-1);
- end;
- function StrToHostAddr6(IP : String) : TIn6_addr;
- Var Part : String;
- IPv6 : TIn6_addr;
- P,J : Integer;
- W : Word;
- Index : Integer;
- ZeroAt : Integer;
- Begin
- FillChar(IPv6,SizeOf(IPv6),0);
- { Every 16-bit block is converted at its own and stored into Result. When }
- { the '::' zero-spacer is found, its location is stored. Afterwards the }
- { address is shifted and zero-filled. }
- Index := 0; ZeroAt := -1;
- J := 0;
- P := Pos(':',IP);
- While (P > 0) and (Length(IP) > 0) and (Index < 8) do
- Begin
- Part := '$'+Copy(IP,1,P-1);
- Delete(IP,1,P);
- if Length(Part) > 1 then { is there a digit after the '$'? }
- Val(Part,W,J)
- else W := 0;
- IPv6.u6_addr16[Index] := HtoNS(W);
- if J <> 0 then
- Begin
- FillChar(IPv6,SizeOf(IPv6),0);
- Exit;
- End;
- if IP[1] = ':' then
- Begin
- ZeroAt := Index;
- Delete(IP,1,1);
- End;
- Inc(Index);
- P := Pos(':',IP); if P = 0 then P := Length(IP)+1;
- End;
- { address a:b:c::f:g:h }
- { Result now a : b : c : f : g : h : 0 : 0, ZeroAt = 2, Index = 6 }
- { Result after a : b : c : 0 : 0 : f : g : h }
- if ZeroAt >= 0 then
- Begin
- Move(IPv6.u6_addr16[ZeroAt+1],IPv6.u6_addr16[(8-Index)+ZeroAt+1],2*(Index-ZeroAt-1));
- FillChar(IPv6.u6_addr16[ZeroAt+1],2*(8-Index),0);
- End;
- StrToHostAddr6:=IPv6;
- End;
- function NetAddrToStr6 (Entry : TIn6_Addr) : ansiString;
- begin
- netaddrtostr6 := HostAddrToStr6((Entry));
- end;
- function StrToNetAddr6(IP : ansiString) : TIn6_Addr;
- begin
- StrToNetAddr6 := StrToHostAddr6(IP);
- end;
|