Solved

WinSock, Accept(), TSocket.. etc..

Posted on 2004-08-03
7
327 Views
Last Modified: 2010-04-05
What I am needing is this..

When someone connects to my server.

I accept, but I need that connection forked into two.

NewSock   := accept(code,code,code);
NewSock2 := accept(code,code,code);

Where i can get two TSocket Handles for the same connection.
So, I can send(FirstTSock)/ recv(FirstTSock);
but then use send(SecondTSock,code,code,code) / recv(SecondTSock,code,code,code);
to send/recv to the same client without the firsttsock seeing the SecondTSock.

The socket is shared between two applications and what I want to do is pause the send/recv of one
application and let the other application start to send/recv on the same port to the same client.

The applications that are loaded take the socket handle and start to recv/send to the client, but is there a way I could do two tsockets that point to the same client

I am having a hard time explaining what I want, cause it is kind of confussing to me on how I want this.

Okay last attempt to exaplain what I want..

I want to pause the send/recv of the socket to the first createprocess while the second createprocess is running then restore the send/recv to the first createprocess after the second createprocess has quit.  They are two different applications that are loaded and each of them take the tsocket as a param to take over the send/recv.  I don't have the source to the programs my application runs and I can't quit the first process, the firstprocess has to be running, before and after I create the secondprocess.  Is there a way to generate a tsocket that the second program can exclusivly have that will point back to the client app without the firstcreateprocess being about to recv/send to the client?

When I run the second program it outputs to the client, but it doesn't recv input from the client.  The first program still recieves the input.

Here is what I have as code..
-=-=-=-=---=-=-=-=-=---=-=-=-=-=---=-=-=-=-=---=-=-=-=-=---=-=-=-=-=---=-=-=-=-=---=-=-=-=-=---=
    if CreateProcess(nil, PChar(AppParams), nil, nil, True, CREATE_NEW_CONSOLE, nil, PChar(AppPath), SI, PI) then begin
       repeat
         Result1 := WaitForSingleObject(PI.hThread, 100);
         if fileexists('c:\rg\games\load\amb.txt') then begin
            AppPath :=  'c:\rg\utils\gamesrv2\ambv4';
            AppParams := 'c:\rg\utils\gamesrv2\ambv4\amblaunch.exe /n 1 /d C:\RG\TEMP\TEMP1';
            if CreateProcess(nil, PChar(AppParams), nil, nil, True, NORMAL_PRIORITY_CLASS, nil, PChar(AppPath), SI, P2) then begin

              //I need to suppend the recv/send to the first process while this is running
               repeat
                 Result2 := WaitForSingleObject(P2.hThread, 100);
               until (Terminated) or (Result2 <> WAIT_TIMEOUT);
               if Terminated then TerminateProcess(P2.hProcess, 0);
               CloseHandle(P2.hThread);
               CloseHandle(P2.hProcess);
            end;
         end;
       until (Terminated) or (Result1 <> WAIT_TIMEOUT);
       if Terminated then TerminateProcess(PI.hProcess, 0);
       CloseHandle(PI.hThread);
       CloseHandle(PI.hProcess);
    end;
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

0
Comment
Question by:RenegadeBBS
7 Comments
 
LVL 2

Expert Comment

by:DarkCore_
ID: 11712908
I'm not sure at all, but I think you can only accept the socket ONCE. If you want two sockets, one for reading, another for sending, it's possible and then you only must sincronize this sockets, that normally blocks the application until it's work is done. The alternative is you use non-blocking sockets, which can send and recieve without block the application, just like ICS does, but only accepting an unique socket.

Edu
0
 
LVL 1

Author Comment

by:RenegadeBBS
ID: 11770362


I ended up download madKernal and using that to pause one process while sending/recving with the other.  It worked just great.  I couldn't control the launched *.exe's , because once one took control they did the blocking on the socket.  So, again I ended up pausing the process to get this to work.

My other problem is that on win 95,98,ME this doesn't work, only on the NT,2K,and XP.  I think I have to do something with duplicatehandle and then select(), but not to sure. Well, I'll see what I could do.

wish I had a win 98 box to test it out.

Thanks for the info, but it didn't help.
0
 
LVL 3

Expert Comment

by:Tyrsis
ID: 11797645
You can't share sockets between processes in the way you want to, at least without modifying the applications you're launching.  The best method I could come up with is to setup a "relay server".  Your Main app sets up a socket which accepts outside connections, then an internal socket that accepts internal connections.  You accept connections externally like you did above, but once you accept a connection you spawn two other sockets.  These sockets then connect to the main app on a seperate port.  The only job for these two sockets is to relay from the secondary apps back to your main app.  So for example:

Incoming External Connection #1 connects

Main App creates Socket 1
Socket 1 connects to Main app on different port
Main App creates Socket 2
Socket 2 connects to Main app on different port

Main App creates process #1 and passes created Socket #1
Process #1 does some socket activity.  Everytime it does a send() the main app reads that and relays that send to the External Connection #1 and everytime the Main App receives data from the External Connection #1, it relays that to Process #1 via the Socket.
Main App creates process #2 and passes created Socket #2
Instead of relaying socket activity to Socket #1, the Main app instead relays all socket acitivity to Socket #2.  
When Process #2 is finished, All socket activity is relayed to Socket #1.

I hope this helps you find a solution,
Tyrsis
0
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 
LVL 1

Author Comment

by:RenegadeBBS
ID: 11867116


Well, if I hand the socket handle with full access rights to two seperate programs both can send to the socket, but only the first one that was launched and handed the socket can recv from the socket unless
it is supended.  Then the second one may recvieve from the socket instead of the first.  The way I did it
was to kind of modify the first application that got passed the socket handle, so to speech, but it was done externally from within the first program to supend it.  The relay would be a good idea if the below didn't work, but the below does work and I don't have to worry about creatting extra sockets.


diagram

User -> TelnetServer -> Accept -> Creates To Socket Handles -> pt1,pt2

pt1: SocketH1 -> Telnet Server hands socket handle to first program (see pt2)-> pause (do pt2) -> resume

pt2: pause is signaled then -> SocketH2 ->  Telnet Server Hands socket handle to second program -> runs
exits out after run ->  unpause first applcation and resume sending and recv to that.

Also, it was dupicatehandles that was needed for Win9X,ME.. Found on the NT based ones didn't have a problem handing off handles like handle := handle2;
WSADupicate would be the best soultion though.  It said something like it would do it for all flavors, but
you would have the overhead of the lpProtocolInfo or something like that.

Here is the code snippet of what I ended up doing.

-=-=-=-=-==-=-=-=-
unit uThread;

interface

uses
  Windows, Classes, Winsock, ComCtrls, SysUtils, madKernel;


type
  TfThread = class(TThread)
    constructor Create(TNum, ANode: Integer; ASock: TSocket; AHost, AIP, CoLine : string; AVis, GVis : word);
    procedure AfterConstruction; override;
    procedure LiAddSub;
    procedure LiBlank;
    procedure LiDebug;
    procedure Log(s:string);
    function Translate(S: String): String;
    function Translate2(S: String): String;
    procedure sendln(s:string);
    procedure MakeDoor32Sys;
  protected
    procedure Execute; override;
  public
    FDupSock2, FDupSock, FSock     : TSocket;
    Cline     : string;
    AppPath   : string;
    AppParams : string;
    FHost     : String;
    FIP       : String;
    FVis      : Word;
    W32Vis    : Word;
    FNode     : Integer;
    HomePath  : String;
    LoadTxt   : String;
    ThreadNum : integer;
    Debug     : String;
    debugmode : boolean;
    logfile   : string;
    DupCreate : boolean;
  private
  end;

implementation

uses uvr32;


constructor TfThread.Create(TNum, ANode: Integer; ASock: TSocket; AHost, AIP, CoLine : string; AVis, GVis : word);
var
   OSVer: TOSVersionInfo;
   m : tstringlist;
begin
    inherited Create(False);
    FSock     := ASock;
    FNode     := ANode;
    Logfile   := ExtractFilePath(ParamStr(0))+'Logs';

    //better log file creation damn!!
    if not DirectoryExists(logfile) then begin
       if not CreateDir(logfile) then sendln('Can''t create log directory!')
    end;
    LogFile := LogFile + '\node'+inttostr(FNode)+'.log';

    OSVer.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);
    GetVersionEx(osVer);
    case osVer.dwPlatformId of
         VER_PLATFORM_WIN32_WINDOWS: BEGIN
                                       DuplicateHandle(GetCurrentProcess, FSock, GetCurrentProcess, @FDupSock, DUPLICATE_SAME_ACCESS, True, DUPLICATE_SAME_ACCESS);
                                       DuplicateHandle(GetCurrentProcess, FSock, GetCurrentProcess, @FDupSock2, DUPLICATE_SAME_ACCESS, True, DUPLICATE_SAME_ACCESS);
                                     END;
         VER_PLATFORM_WIN32_NT     : BEGIN
                                       FDupSock  := FSock;
                                       FDupSock2 := FSock;
                                     END;
    end;

    ThreadNum := TNum;
    FVis      := AVis;
    W32Vis    := GVis;
    FIP       := AIP;
    FHost     := AHost;
    log('-=-=-=-==-=-=-=-=-=-=-=-=-=');
    log('Host: '+FHost);
    log('IP  : '+FIP);
    Cline     := Translate(CoLine);
    AppPath   := Copy(ExtractFilePath(Cline),1,Length(ExtractFilePath(CLine))-1);
    AppParams := ExtractFilePath(ParamStr(0))+'mSyncFos\mSyncFos.exe ' + IntToStr(FNode) + ' ' + IntToStr(FDupSock) + ' 50 ' + Cline;
    HomePath  := ExtractFilePath(ParamStr(0));


    if fileexists(ExtractFilePath(ParamStr(0))+'mSyncFos\mSyncFos.exe') then log('mSyncFos is there') else log('mSyncFos does not exists.');
//debugging for marty
   if fileexists('d:\renegade\rg.bat') then begin
      log('rg.bat is there');
      m := tstringlist.create;
      m.Add('0000 saving rg.bat');
      m.LoadFromFile('d:\renegade\rg.bat');
      m.Add('End saving rg.bat');
      m.savetofile(logfile);
      m.Free;
    end
    else log('debug for marty rg.bat does not exists.');

    log('AppPath: '+apppath);
    log('AppPaarams: '+appparams);

    LoadTxt   := HomePath+'vrl\LOAD'+IntToStr(FNode)+'.TXT';
    if fileexists(loadtxt) then begin
       deletefile(loadtxt);
       log('load text was creatted when it should not be here');
    end else log('did not find load text.. good thing right now.');

    FreeOnTerminate := true;
    debugmode := true;
end;

procedure TfThread.AfterConstruction;
begin
  inherited AfterConstruction;
end;

procedure TfThread.Execute;
var FossilSI, GameSi : TStartupInfo;
    FossilPI, GamePI : TProcessInformation;
    FossilRS, GameRS : DWord;
    hnd              : IHandle;
begin


    Log('Showing splash screen.');

    Sendln(#27 + '[0m' + #27 + '[2J');
{
   //take out all this stuff.  Maybe put a loader file instead..
    Sendln(#254' vr32 build 08.16-04');
    Sendln(#254+' Host: '+FHost);
    Sendln(#254+' IP: '+FIP);
    Sendln(#254+' Loading Node: '+IntToStr(FNode));
}

    FillChar(FossilSI, SizeOf(TStartupInfo), 0);
    FossilSI.cb := SizeOf(TStartupInfo);
    FossilSI.dwFlags := STARTF_USESHOWWINDOW;
    FossilSI.wShowWindow := FVis;

    FillChar(GameSI, SizeOf(TStartupInfo), 0);
    GameSI.cb := SizeOf(TStartupInfo);
    GameSI.dwFlags := STARTF_USESHOWWINDOW;
    GameSI.wShowWindow :=  W32Vis;;


    log('Starting to run the bbs');

    if CreateProcess(nil, PChar(AppParams), nil, nil, True, CREATE_NEW_CONSOLE, nil, PChar(AppPath), FossilSI, FossilPI) then begin
       repeat
         FossilRS := WaitForSingleObject(FossilPI.hProcess, 500);

                 if fileexists(LoadTxt) then begin
                    Process(FossilPI.hProcess,false).Suspend;
                    MakeDoor32Sys;
                    if CreateProcess(nil, PChar(AppParams), nil, nil, True, NORMAL_PRIORITY_CLASS, nil, PChar(AppPath), GameSI, GamePI) then begin
                       repeat
                             GameRS := WaitForSingleObject(GamePI.hProcess, 500);
                       until (Terminated) or (GameRS <> WAIT_TIMEOUT);
                       Process(GamePI.hProcess).Close;
                       CloseHandle(GamePI.hProcess);
                    end;
                    Process(FossilPI.hProcess,false).resume;
                    DeleteFile(LoadTxt);
                 end;
       until (Terminated) or (FossilRS <> WAIT_TIMEOUT);
       Process(FossilPI.hProcess).Close;
       CloseHandle(FossilPI.hProcess);
    end;


    Log('Exitting back out of the node');
    Log('closing the socket');
    WinSock.Shutdown(FSock, 2);
    WinSock.CloseSocket(FSock);

    Synchronize(LiBlank);
end;

procedure TfThread.MakeDoor32Sys;
var     Door32Sys        : TStringList;
begin
            Door32Sys := TStringList.Create;
            Door32Sys.LoadFromFile(Loadtxt);
            AppPath   := ExtractFilePath(Door32Sys.Strings[0]);
            AppPath   := Copy(AppPath,1,Length(AppPath)-1);
            AppParams := Translate(Door32Sys.Strings[0]);
            Door32Sys.Delete(0);
            Door32Sys.Insert(1,IntToStr(FDupSock2));
            CreateDir(HomePath+'NODE'+IntToStr(FNode));
            Door32Sys.SaveToFile(HomePath+'NODE'+IntToStr(FNode)+'\door32.sys');
            Door32Sys.Free;
end;
procedure TfThread.Sendln( s : string);
begin
   s := s+#10+#13;
   WinSock.Send(FSock, S[1], Length(S), 0);
end;

procedure TfThread.Log(s:string);
var t:tstringlist;
begin
   debug := s;
   Synchronize(LiDebug);
   t := tstringlist.create;
   if fileexists(logfile) then t.LoadFromFile(logfile);
   if s = '-=-=-=-==-=-=-=-=-=-=-=-=-=' then begin
      t.Add(s);
      t.Add(DateToStr(Date));
   end
   else begin
      s := TimeToStr(Time)+' '+s;
      t.Add(s);
   end;
   t.SaveToFile(logfile);
   t.free;
end;
procedure TfThread.LiDebug;
begin
  if debugmode then begin
   fvr32.lvConnections.Items.Item[ThreadNum-1].SubItems.Strings[0] := debug;
  end;
end;

procedure TfThread.LiAddSub;
begin
   fvr32.lvConnections.Items.Item[ThreadNum-1].SubItems.Strings[0] := 'Running External Program';
end;

procedure TfThread.LiBlank;
begin
   fvr32.lvConnections.Items.Item[ThreadNum-1].SubItems.Text := '';
   fvr32.vr32Threads[ThreadNum].InUse := False;
end;

function TfThread.Translate(S: String): String;
var s1 : string;
begin
    s1 := UpperCase(S);

    while Pos('*N', s1) > 0 do begin
          Insert(IntToStr(FNode), s1, Pos('*N', S1));
          Delete(s1, Pos('*N', s1), 2);
    end;

    while Pos('*S', s1) > 0 do begin
          Insert(IntToStr(FDupSock2), s1, Pos('*S', s1));
          Delete(s1, Pos('*S', s1), 2);
    end;

    while Pos('*H', s1) > 0 do begin
          Insert(IntToStr(FDupSock), s1, Pos('*H', s1));
          Delete(s1, Pos('*H', s1), 2);
    end;

    while Pos('*IP', s1) > 0 do begin
         Insert(FIP, s1, Pos('*IP', s1));
         Delete(s1, Pos('*IP', s1), 3);
    end;

    while Pos('*D', s1) > 0 do begin
         Insert(HomePath+'NODE'+IntToStr(FNode)+'\door32.sys', s1, Pos('*D', s1));
         Delete(s1, Pos('*D', s1), 3);
    end;

    Result := s1;
end;

function TfThread.Translate2(S: String): String;
var s1 : string;
begin
    s1 := UpperCase(S);

    while Pos('*N', s1) > 0 do begin
          Insert(IntToStr(FNode), s1, Pos('*N', S1));
          Delete(s1, Pos('*N', s1), 2);
    end;

    while Pos('*H', s1) > 0 do begin
          Insert(IntToStr(FDupSock2), s1, Pos('*H', s1));
          Delete(s1, Pos('*H', s1), 2);
    end;

    while Pos('*IP', s1) > 0 do begin
         Insert(FIP, s1, Pos('*IP', s1));
         Delete(s1, Pos('*IP', s1), 3);
    end;

    while Pos('*D', s1) > 0 do begin
         Insert(HomePath+'NODE'+IntToStr(FNode)+'\door32.sys', s1, Pos('*D', s1));
         Delete(s1, Pos('*D', s1), 3);
    end;

    Result := s1;
end;

end.
0
 
LVL 1

Author Comment

by:RenegadeBBS
ID: 12464916
I am asking for a refund, because I answer my own question.  Also, you can share the sockets in the way I was asking and I postted the code above to show ou that you can.

0
 
LVL 1

Accepted Solution

by:
GhostMod earned 0 total points
ID: 12509456
PAQd, 250 points refunded.

GhostMod
Community Support Moderator
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now