{$IFDEF OS2}
{$Delphi+}
{$ENDIF}

Unit
  kSockFun;

(*

  Copyright (c) 1982, 1985, 1986 Regents of the University of California.
  All rights reserved.

  Redistribution and use in source and binary forms are permitted
  provided that this notice is preserved and that due credit is given
  to the University of California at Berkeley. The name of the University
  may not be used to endorse or promote products derived from this
  software without specific prior written permission. This software
  is provided ``as is'' without express or implied warranty.

  @(#)socket.h    7.2 (Berkeley) 12/30/87

  VP conversion by Thomas Mueller

*)

Interface

Uses
{$IFDEF OS2}
  OS2Def,
  IBMSO32,
  IBMTCP32,
{$ELSE}
  windows,
  W32Sock,
  Os2Comp,
{$ENDIF}
  Sysutils,
  kSockDef;

Function SockErrorNo: ApiRet;

Function SockAccept (_SockDesc: TSockDesc; _SockAddr: pSockAddr; Var _SockAddrLen: ULong): tSockDesc;
Function SockBind (_SockDesc: TSockDesc; Const _SockAddr: tSockAddr): ApiRet;
Function SockCancel (_SockDesc: TSockDesc): ApiRet;
Function SockConnect (_SockDesc: TSockDesc; Const _SockAddr: tSockAddr): ApiRet;
Function SockShutdown (_SockDesc: TSockDesc; _how: ULong): ApiRet;

{$IFDEF os2}
Function SockGetHostID: ULong;
{$ENDIF}
Function SockGetSockAddr (_SockDesc: TSockDesc; Var _SockAddr: TSockAddr): LongInt;
Function SockGetSockOpt (_SockDesc: TSockDesc; _Level, _OptName: ULong; _OptVal: PChar; Var _OptLen: ULong): ApiRet;
Function SockSetSockOpt (_SockDesc: TSockDesc; _Level: ULong; _OptName: ULong; _OptVal: PChar; _OptLen: ULong ): ApiRet;
Function SockSetBlockingIO (_SockDesc: TSockDesc; _BlockingIO: boolean): ApiRet;
Function SockListen (_SockDesc: TSockDesc; _SockQueue: ULong): ApiRet;
Function SockRecv (_SockDesc: TSockDesc; _SockBuffer: Pointer; _SockBufLen: ULong; _SockFlags: ULong): ApiRet;
Function SockSend (_SockDesc: TSockDesc; _SockBuffer: Pointer; _SockBufLen: ULong; _SockFlags: ULong ): ApiRet;
Function SockSocket (_SockFamily: word; _SockType: Word; _SockProtocol: Word): tSockDesc;
Function SockClose (_SockDesc: tSockDesc): ApiRet;
Function SockErrNo: ApiRet;
Function SockInit: ApiRet;

Function SockGetHostAddrByName (_HostName: String): ULong;
Function SockGetHostNameByAddr (_HostAddr: PIn_Addr): String;
Function SockGetHostname: String;

Function SockGetServByName (_Name, _Proto: String): PServEnt;
Function SockGetServPortByName (_Name, _Proto: String): SmallInt;

Function SockHtonl (_Input: LongInt): LongInt;
Function SockHtons (_Input: SmallInt): SmallInt;

Function SockNtohl (_Input: LongInt): LongInt;
Function SockNtohs (_Input: SmallInt): SmallInt;

{$IFDEF OS2}
Function SockDataAvail (_SockDesc: TSockDesc): ulong;
{$ENDIF}

Function SockSelect (_SockDesc: TSockDesc): ApiRet;
Function SockInetAddr (_s: String): TIn_Addr;

{$IFDEF WIN32}
{$R UTWMW32}
{$ELSE}
{$R UTWMOS2}
{$ENDIF}

Implementation

Function SockErrorNo: ApiRet;
Begin
{$IFDEF OS2}
  Result := Sock_ErrNo;
{$ELSE}
  Result := MS_GetLastError;
{$ENDIF}
End;

Function SockGetServByName (_Name, _Proto: String): PServEnt;
Begin
  _Name := _Name + #0;
  _Proto := _Proto + #0;
  Result := GetServByName (@_Name [1], @_Proto [1]);
End;

Function SockGetServPortByName (_Name, _Proto: String): SmallInt;
Var
  ServEnt: PServEnt;

Begin
  ServEnt := SockGetServByName (_Name, _Proto);
  If Assigned (ServEnt) Then Result := ServEnt^. S_Port Else Result := -1;
End;

Function SockHtonl (_Input: LongInt): LongInt;
Begin
  Result := htonl (_Input);
End;

Function SockHtons (_Input: SmallInt): SmallInt;
Begin
  Result := htons (_Input);
End;

Function SockNtohl (_Input: LongInt): LongInt;
Begin
  Result := ntohl (_Input);
End;

Function SockNtohs( _Input: SmallInt ): SmallInt;
Begin
  Result := ntohs( _input );
End;

Function SockAccept (_SockDesc: TSockDesc; _SockAddr: PSockAddr; Var _SockAddrLen: ULong): ApiRet;
Begin
  Result := Accept (_SockDesc, _SockAddr, @_SockAddrLen);
End;

Function SockBind (_SockDesc: TSockDesc; Const _SockAddr: TSockAddr): ApiRet;
begin
  SockBind := Bind (_SockDesc, @_SockAddr, SockAddr_Len);
end;

Function SockConnect (_SockDesc: TSockDesc; Const _SockAddr: TSockAddr): ApiRet;
Begin
  SockConnect := Connect (_SockDesc, @_SockAddr, SockAddr_Len);
End;

Function SockCancel (_SockDesc: TSockDesc): ApiRet;
Begin
{$IFDEF OS2}
  Result := So_Cancel (_SockDesc);
{$ELSE}
  Result := MS_CancelBlockingCall;
{$ENDIF}
End;

Function SockShutDown (_SockDesc: TSockDesc; _How: ULong): ApiRet;
Begin
  SockShutdown := ShutDown (_SockDesc, _How);
End;

{$ifdef os2}
  function SockGetHostID: ULong;
    begin
    SockGetHostID := SockHtonl(gethostid);
  end;
{$endif}

  function SockGetSockAddr(_SockDesc: tSockDesc; var _SockAddr: tSockAddr): Longint;
    var
      SLength: longint;
    begin
    fillchar(_SockAddr,sizeof(_SockAddr),#0);
    SLength:=SizeOf(_SockAddr);
    result:=getsockname(_SockDesc, @_SockAddr, SLength);
  end;

  function SockSetBlockingIO(_SockDesc: tSockDesc;
                             _BlockingIO: boolean): ApiRet;
  {$ifdef os2}
    var
      Arg: ULong;
  {$endif}
    begin
  {$ifdef os2}
    if _BlockingIO then
      Arg:= 0
    else
      Arg:= 1;
    Result:=ioctl(_SockDesc, FIONBIO, @Arg, SizeOf(Arg));
  {$else}
    Result:=-1;
  {$endif}
  end;

Function SockGetSockOpt (_SockDesc: tSockDesc; _Level, _OptName: ULong; _OptVal: PChar; var _OptLen: ULong): ApiRet;
begin
  Result := GetSockOpt (ULONG (_SockDesc), Integer (_Level), Integer (_OptName), _OptVal, Integer (_OptLen));
end;

function SockSetSockOpt(_SockDesc: tSockDesc; _Level: uLong; _OptName: Ulong; _OptVal: pChar; _OptLen: uLong ): ApiRet;
begin
  Result := SetSockOpt(_SockDesc, _Level, _OptName, _OptVal, _OptLen);
end;

{$ifdef os2}
function SockDataAvail(_SockDesc: tSockDesc): ULONG;
begin
  if ioctl(_SockDesc, FIONREAD, @Result, SizeOf( Result ) ) = -1 then Result:=$FFFFFFFF;
end;
{$endif}

  function SockListen(_SockDesc: tSockDesc;
                      _SockQueue:  ULong): ApiRet;
    begin
    SockListen := listen(_SockDesc, _SockQueue);
  end;

  function SockSelect(_SockDesc: tSockDesc ): ApiRet;
    var
    {$ifdef os2}
      SockCopy: ULONG;
    {$else}
      SockArr: TFDSet;
      Timeout: TTimeVal;
    {$endif}
    begin
  {$ifdef os2}
    SockCopy:=_SockDesc;
    Result:=select(@SockCopy, 1, 0, 0, 0);
  {$else}
    SockArr.fd_count:=1;
    SockArr.fd_array[0]:=_SockDesc;
    Timeout.tv_sec:=0;
    Timeout.tv_usec:=0;
    Result:=MS_select(0, @SockArr, nil, nil, @Timeout);
  {$endif}
  end;

  function SockRecv(_SockDesc: tSockDesc;
                    _SockBuffer: pointer;
                    _SockBufLen: ULong;
                    _SockFlags:  ULong): ApiRet;
    begin
    SockRecv := recv(_SockDesc,
                     _SockBuffer,
                     _SockBufLen,
                     _SockFlags);
  end;

  function SockSend(_SockDesc: tSockDesc;
                    _SockBuffer: pointer;
                    _SockBufLen: ULong;
                    _SockFlags:  ULong): ApiRet;
    begin
    SockSend := send(_SockDesc,
                         _SockBuffer,
                         _SockBufLen,
                         _SockFlags);
  end;

function SockSocket(_SockFamily: word; _SockType: word; _SockProtocol: word): tSockDesc;
begin
  SockSocket := Socket (_SockFamily, _SockType, _SockProtocol);
end;

function SockClose(_SockDesc: tSockDesc): ApiRet;
begin
{$ifdef os2}
  Result:=soclose(_SockDesc);
{$else}
  Result:=MS_closesocket(_SockDesc);
{$endif}
end;

function SockErrNo: ApiRet;
begin
{$ifdef os2}
  SockErrNo := Sock_ErrNo;
{$else}
  Result := MS_getlasterror;
{$endif}
end;

Function SockInit: ApiRet;
Var
  Data : TWSAData;

Begin
{$IFDEF OS2}
  SockInit := Sock_Init;
{$ELSE}
  SockInit := MS_StartUp ($0101, @Data);
{$ENDIF}
End;

Function SockGetHostByName (Hostname: String): pointer;
Begin
  HostName := HostName + #0;
  Result := gethostbyname (@HostName [1]);
End;

Function SockGetHostAddrByName (_HostName: String): ULong;
Var
  rc     : pHostEnt;
  InAddr : tIn_Addr;

Begin
  rc := SockGetHostByName (_Hostname);
  If Assigned (rc) Then
  Begin
    InAddr := rc^. H_Addr_List^^;
    Result := InAddr. IPAddr;
  End Else
    Result := $FFFFFFFF;
End;

Function SockGetHostByAddr (HostAddr: PIn_Addr; HostAddrLen: ULong; HostAddrType: ULong): Pointer;
Begin
  SockGetHostByAddr := GetHostByAddr (HostAddr, HostAddrLen, HostAddrType);
End;

Function SockGetHostNameByAddr (_HostAddr: PIn_Addr): String;
Var
  i     : Integer;
  rc    : pHostEnt;
  HName : String;

Begin
  rc := SockGetHostByAddr (_HostAddr, In_Addr_Len, AF_INET);

  If ULong (rc) <> 0 Then
  Begin
    i := 0;
    HName := '';
    While rc^. H_Name^ [i] <> #0 Do
    Begin
      HName := HName + rc^. H_Name^ [i];
      Inc (i);
    End;
  End Else
    HName := 'hostname not found';

  SockGetHostNameByAddr := HName;
End;

Function SockGetHostname: String;
Var
  I, SResult : LongInt;
  HostName   : String;

Begin
  i := 1;
  FillChar (HostName, SizeOf (HostName), #0);
  SResult := GetHostName (@HostName [1], SizeOf (HostName));
  While (i < SizeOf (HostName)) And (Hostname [i] <> #0) do inc(I);
  If (I > 1) Then SetLength(HostName, I) else HostName := 'amnesiac';
  SockGetHostname := HostName;
End;

Function SockInetAddr (_S: String): TIn_Addr;
Begin
  _S := _S + #0;
  Result. IPAddr := Inet_Addr (@_S [1]);
End;

Initialization
  SockInit;
End.