⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 awwnsock.pas

📁 测试用例
💻 PAS
📖 第 1 页 / 共 4 页
字号:
          if FOptSupga <> tnoNegotiating then begin
            if DefOptSupga then begin
              SendDo(Option);
            end else begin
              SendDont(Option);
            end;
          end else begin
            FOptSupga := tnoTrue;
          end;
        end;
        TELNETOPT_ECHO   :
        begin
          if FOptEcho <> tnoNegotiating then begin
            if DefOptEcho then begin
              SendDo(Option);
            end else begin
              SendDont(Option);
            end;
          end else begin
            FOptEcho := tnoTrue;
          end;
        end else begin
          SendDont(Option);
        end;
      end;
    end else begin
      Result := False;                                               
      if FDispatcher.DLoggingOn then
        FDispatcher.AddDispatchEntry(dtTelnet, dstCommand, Ord(Command), nil, 0);
    end;
  end;
end;

{ Process & strip telnet commands -- calling method is responsible for }
{ ensuring there is at least Size bytes left in the Dest buffer }
function TWsConnection.ProcessCommands(Dest : PChar; Size : Cardinal) : Integer;
var
  StartDest, EndBuf, Temp : PChar;

  function NextChar : Char;
  begin
    if (FInCursor + 1) = FInBufEnd then
      Result := FInBuf^
    else
      Result := (FInCursor + 1)^;
  end;

begin
  StartDest := Dest;
  EndBuf := FInCursor + Size;
  while FInCursor < EndBuf do begin
    if FInCursor^ <> TELNET_IAC then begin
      { ASCII mode, and CR/NULL received -- strip the null }
      if (FOptBinary = tnoFalse) and (FInCursor^ = TELNET_CR) and
         (NextChar = TELNET_NULL) then begin
        Dest^ := FInCursor^;
        Dest := Dest + 1;
        FInCursor := FInCursor + 2;
        if FInCursor > FinBufEnd then begin
          FInCursor := FInBuf + 1;
          Break;
        end;
      end else begin                                                
        { Copy over verbatim }
        Dest^ := FInCursor^;
        FInCursor := FInCursor + 1;
        Dest := Dest + 1;
      end;                                                            
    end else begin
      if ((FInCursor + 1) = FInBufEnd) and (FInEnd = FInBuf) then
        break;
      if NextChar = TELNET_IAC then begin
        { It's an escaped IAC -- copy a single over }
        Dest^ := FInCursor^;
        Dest := Dest + 1;
        FInCursor := FInCursor + 2;
        if FInCursor > FinBufEnd then begin
          FInCursor := FInBuf + 1;
          break;
        end;
      end else begin
        { If at the end of the buffer, and made it this far, exit loop }
        if (FInCursor + 1) = FInBufEnd then begin
          FInCursor := FInCursor + 1;
          Break;
        end;
        if NextChar <> TELNET_SB then begin
          { It's an actual command -- strip it and act on it }
          if HandleCommand((FInCursor + 1)^, (FInCursor + 2)^) then
            FInCursor := FInCursor + 3
          else
            FInCursor := FInCursor + 2;
        end else begin
          { It's a subnegotation situation -- look for the end }
          if (FInCursor + 2)^ = TELNETOPT_TERM then
            SendTerminal;
          Temp := FindIAC((FInCursor + 1), EndBuf - (FInCursor + 1));
          if (Temp + 1)^ = TELNET_SE then
            FInCursor := Temp + 2;
        end;
      end;
    end;
  end;
  Result := (Dest - StartDest);
end;

{ Read from Winsock and process telnet commands if applicable }
function TWsConnection.ReadBuf(var Buf; Size : Integer) : Integer;
var
  NumRead,
  NumRead2 : Integer;
  CanRead,
  CanRead2 : Cardinal;

  {$IFDEF Win32}
  function MinCard(C1, C2 : Cardinal) : Cardinal; assembler;
  asm
    cmp   eax,edx
    jbe   @1
    mov   eax,edx
  @1:
  end;
  {$ELSE}
  function MinCard(C1, C2 : Cardinal) : Cardinal; assembler;
  asm
    mov   ax,C1
    mov   bx,C2
    cmp   ax,bx
    jbe   @1
    mov   ax,bx
  @1:
  end;
  {$ENDIF}

  procedure UpDatePtr(var SPtr : PChar; Delta : Integer);
  begin
    SPtr := SPtr + Delta;
    if SPtr >= FInBufEnd then
      SPtr := FInBuf + (SPtr - FInBufEnd);
  end;

  procedure MoveChunk(BeginPt, EndPt : PChar);
  var
    CanMove : Cardinal;
  begin
    CanMove := (EndPt - BeginPt);
    CanMove := MinCard(CanMove, (Size - Result));
    Move(BeginPt^, (PChar(@Buf)+Result)^, CanMove);
    Inc(Result, CanMove);

   if CanMove > 0 then begin
     UpDatePtr(FInStart, CanMove);
     if FInStart >= FInBufEnd then
       FInStart := FInBuf;
   end;
   if (FInStart <> FInEnd) or (CanMove > 0) then
     FInBufFull := False;
   if FInStart <= FInEnd then
     if (FInCursor < FInStart) or (FInCursor >= FInEnd) then
       FInCursor := FInStart
     else
   else
     if (FInCursor < FInStart) and (FInCursor >= FInEnd) then
       FInCursor := FInStart;
  end;

  procedure ProcessChunk(BuffEnd : Boolean);
  var
    CanMove, Processed : Cardinal;
    EndPt, ResetPt : PChar;
  begin
    if BuffEnd then begin
      EndPt := FInBufEnd;
      ResetPt := FInBuf;
    end else begin
      EndPt := FInEnd;
      ResetPt := FInEnd;
    end;
    CanMove := MinCard((EndPt - FInCursor), (Size - Result));
    if CanMove > 0 then begin
      Processed := ProcessCommands(PChar(@Buf)+Result, CanMove);
      Inc(Result, Processed);
      if FInCursor >= EndPt then
        FInCursor := ResetPt;
      FInStart := FInCursor;
      FInBufFull := False;
    end;
  end;

begin
  Result := 0;
  if (FInEnd >= FInStart) and not FInBufFull then begin
    { Not currently wrapped -- but we can if need be }
    CanRead := (FInBufEnd - FInEnd);
    CanRead2 := (FInStart - FInBuf);
    NumRead := ApdSocket.ReadSocket(FCommSocket, FInEnd^, CanRead, 0);
    if NumRead = SOCKET_ERROR then
      NumRead := 0;
    if NumRead > 0 then begin
      FInEnd := FInEnd + NumRead;
      if FInEnd = FInBufEnd then
        FInEnd := FInBuf;
      if FInStart = FInEnd then
        FInBufFull := True;
    end;
    if Size = 0 then
      Exit;
    if NumRead = Integer(CanRead) then begin                         
      { Try again with wrap -- possibly more to read }
      NumRead2 := ApdSocket.ReadSocket(FCommSocket, FInBuf^, CanRead2, 0);
      if NumRead2 = SOCKET_ERROR then
        NumRead2 := 0;
      if NumRead2 > 0 then begin
        FInEnd := FInBuf + NumRead2;
        FInBufFull := (FInStart = FInEnd);
      end;
      if NumRead2 > 0 then begin
        { Successful wrap read }
        FInCursor := FindIAC(FInCursor, (FInBufEnd - FInCursor));
        { Are we processing telnet stuff? }
        if FInCursor = FInBufEnd then begin
          { No IACs found }
          FInCursor := FInBuf;
          MoveChunk(FInStart, FInBufEnd);
        end else begin
          { Move data prior to IAC }
          MoveChunk(FInStart, FInCursor);
          { Process and move beyond IAC }
          ProcessChunk(True);
          if FInCursor <> FInBuf then
            Exit;
        end;
        { Ready to process wrapped data }
        FInCursor := FindIAC(FInCursor, (FInEnd - FInCursor));
        { Are we processing telnet stuff? }
        if FInCursor = FInEnd then begin
          { No IACs found }
          FInCursor := FInStart;
          MoveChunk(FInBuf, FInEnd);
        end else begin
          { Move data prior to IAC }
          MoveChunk(FInBuf, FInCursor);
          { Process and move beyond IAC }
          ProcessChunk(False);
        end;
      end else begin
        { We didn't wrap }
        FInCursor := FindIAC(FInCursor, (FInEnd - FInCursor));
        { Are we processing telnet stuff? }
        if FInCursor = FInEnd then begin
          { No IACs found }
          FInCursor := FInStart;
          MoveChunk(FInStart, FInEnd);
        end else begin
          { Move data prior to IAC }
          MoveChunk(FInStart, FInCursor);
          { Process and move beyond IAC }
          ProcessChunk(False);
        end;
      end;
    end else begin
      { Read all there was available -- no need to wrap }
      FInCursor := FindIAC(FInCursor, (FInEnd - FInCursor));
      { Are we processing telnet stuff? }
      if FInCursor = FInEnd then begin
        { No IACs found }
        FInCursor := FInStart;
        MoveChunk(FInStart, FInEnd);
      end else begin
        { Move data prior to IAC }
        MoveChunk(FInStart, FInCursor);
        { Process and move beyond IAC }
        ProcessChunk(False);
      end;
    end;
  end else begin
    { Already wrapped }
    if not FInBufFull then begin
      { Read as much as we can }
      CanRead := (FInStart - FInEnd);
      NumRead := ApdSocket.ReadSocket(FCommSocket, FInEnd^, CanRead, 0);
      if NumRead = SOCKET_ERROR then
        NumRead := 0;
      FInEnd := FInEnd + NumRead;
      if FInEnd = FInBufEnd then
        FInEnd := FInBuf;
      if (NumRead > 0) and (FInStart = FInEnd) then
        FInBufFull := True;
    end;
    if Size = 0 then
      Exit;
    { Is the cursor on the first half or second half of wrap? }
    if FInCursor >= FInStart then begin
      { Yes, cursor is on first half }
      FInCursor := FindIAC(FInCursor, (FInBufEnd - FInCursor));
      if FInCursor = FInBufEnd then begin
        { No IACs found }
        FInCursor := FInStart;
        MoveChunk(FInStart, FInBufEnd);
        if (FInStart <> FInEnd) then
          FInBufFull := False;
        FInCursor := FInStart;
      end else begin
        { Move data prior to IAC }
        MoveChunk(FInStart, FInCursor);
        { Process and move beyond IAC }
        ProcessChunk(True);
        if (FInStart <> FInEnd) then
          FInBufFull := False;
        FInCursor := FInStart;
      end;
    end else begin
      { Cursor is on second half }
      FInCursor := FindIAC(FInCursor, (FInEnd - FInCursor));
      { Move first half }
      MoveChunk(FInStart, FInBufEnd);
      { Process second half up to IAC }
      MoveChunk(FInBuf, FInCursor);
    end;
  end;
end;

destructor TWsConnection.Destroy;
begin
  FreeMem(FInBuf, FInSize);
  FreeMem(FOutBuf, FOutSize);
  inherited Destroy;
end;

function TWsConnection.GetConnected : Boolean;
begin
 Result := (ConnectionState = wcsConnected);
end;

{ Get number of characters currently in the input buffer }
function TWsConnection.GetInChars : Cardinal;
var
  Buf : Char;
begin
  if FInBufFull then
    Result := FInSize
  else begin
    if ConnectionState = wcsConnected then
      { Force a read from Winsock if anything is available }
      ReadBuf(Buf, 0);
    if FInBufFull then
      Result := FInSize
    else
      if FInEnd >= FInStart then
        Result := FInEnd - FInStart
      else
        Result := LongInt(FInSize) - (FInStart - FInEnd);             
  end;
end;

{ Get number of characters currently in the output buffer }
function TWsConnection.GetOutChars : Cardinal;
var
  Buf : Char;
begin
  if (ConnectionState = wcsConnected) then
    { Force a write to Winsock if buffer has data }
    if FOutBufFull or (FOutStart <> FOutEnd) then begin
      WriteBuf(Buf, 0);
    end else begin
      FSimBuf := 0;
    end;
  Result := FSimBuf;
end;

{ Set the connection state and DCD if necessary }
procedure TWsConnection.SetConnectionState(Value : TWsConnectionState);
begin
  if FConnectionState <> Value then begin
    if FConnectionState = wcsConnected then
      ClearFlag(FDispatcher.ModemStatus, DCDMask);
    FConnectionState := Value;
    if FConnectionState = wcsConnected then
      SetFlag(FDispatcher.ModemStatus, DCDMask);
  end;
end;

{ Send Telnet DO command with option }
procedure TWsConnection.SendDo(Option: Char);
var
  Buf : array[1..3] of Char;
begin
  Buf[1] := TELNET_IAC;
  Buf[2] := TELNET_DO;
  Buf[3] := Option;
  ApdSocket.WriteSocket(FCommSocket, Buf, SizeOf(Buf), 0);
  if FDispatcher.DLoggingOn then
    FDispatcher.AddDispatchEntry(dtTelnet, dstSDo, Ord(Option), nil, 0);
end;

{ Send Telnet DONT command with option }
procedure TWsConnection.SendDont(Option: Char);
var
  Buf : array[1..3] of Char;
begin
  Buf[1] := TELNET_IAC;
  Buf[2] := TELNET_DONT;
  Buf[3] := Option;
  ApdSocket.WriteSocket(FCommSocket, Buf, SizeOf(Buf), 0);
  if FDispatcher.DLoggingOn then
    FDispatcher.AddDispatchEntry(dtTelnet, dstSDont, Ord(Option), nil, 0);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -