comp.lang.ada
 help / color / mirror / Atom feed
* Sockets Example Sought
@ 2012-11-23 17:17 Robert Love
  2012-11-23 18:32 ` Simon Wright
  2012-11-28  4:43 ` anon
  0 siblings, 2 replies; 12+ messages in thread
From: Robert Love @ 2012-11-23 17:17 UTC (permalink / raw)


Does anyone have an example of a multi-client server in Ada they care 
to share?  It should use the Gnat.Sockets package.  I've seen samples 
but they don't seem complete, or at least my understanding isn't 
complete<grin>.

Thanks in advance.





^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Sockets Example Sought
  2012-11-23 17:17 Sockets Example Sought Robert Love
@ 2012-11-23 18:32 ` Simon Wright
  2012-11-23 21:58   ` Robert Love
  2012-11-28  4:43 ` anon
  1 sibling, 1 reply; 12+ messages in thread
From: Simon Wright @ 2012-11-23 18:32 UTC (permalink / raw)


Robert Love <rblove@airmail.net> writes:

> Does anyone have an example of a multi-client server in Ada they care
> to share?  It should use the Gnat.Sockets package.  I've seen samples
> but they don't seem complete, or at least my understanding isn't
> complete<grin>.
>
> Thanks in advance.

task body Server in http://goo.gl/bXVw7 ? (lines 59 .. 143)



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Sockets Example Sought
  2012-11-23 18:32 ` Simon Wright
@ 2012-11-23 21:58   ` Robert Love
  2012-11-23 22:40     ` Dmitry A. Kazakov
  2012-11-23 23:08     ` Simon Wright
  0 siblings, 2 replies; 12+ messages in thread
From: Robert Love @ 2012-11-23 21:58 UTC (permalink / raw)


On 2012-11-23 18:32:52 +0000, Simon Wright said:

> Robert Love <rblove@airmail.net> writes:
> 
>> Does anyone have an example of a multi-client server in Ada they care
>> to share?  It should use the Gnat.Sockets package.  I've seen samples
>> but they don't seem complete, or at least my understanding isn't
>> complete<grin>.
>> 
>> Thanks in advance.
> 
> task body Server in http://goo.gl/bXVw7 ? (lines 59 .. 143)

What happens at line 120, the else clause on if Server = Socket_Server? 
 Is that where data is read in on the socket?

I assume the client opens the socket and the server detects it, then at 
various times the client makes data requests by sending string data.

The Respond function called just seems to call HTTP.Respond, which is 
not in this file.





^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Sockets Example Sought
  2012-11-23 21:58   ` Robert Love
@ 2012-11-23 22:40     ` Dmitry A. Kazakov
  2012-11-24 18:27       ` Robert Love
  2012-11-23 23:08     ` Simon Wright
  1 sibling, 1 reply; 12+ messages in thread
From: Dmitry A. Kazakov @ 2012-11-23 22:40 UTC (permalink / raw)


On Fri, 23 Nov 2012 15:58:53 -0600, Robert Love wrote:

> On 2012-11-23 18:32:52 +0000, Simon Wright said:
> 
>> Robert Love <rblove@airmail.net> writes:
>> 
>>> Does anyone have an example of a multi-client server in Ada they care
>>> to share?  It should use the Gnat.Sockets package.  I've seen samples
>>> but they don't seem complete, or at least my understanding isn't
>>> complete<grin>.
>>> 
>>> Thanks in advance.
>> 
>> task body Server in http://goo.gl/bXVw7 ? (lines 59 .. 143)
> 
> What happens at line 120, the else clause on if Server = Socket_Server? 
>  Is that where data is read in on the socket?

Socket-select might be a bit difficult to start with. Unless you expect
hundreds of simultaneous connections, there is a much simpler pattern that
uses 1-2 tasks (half- or full-duplex I/O) per connection with so-called
blocking sockets:

   Client : Sock_Addr_Type;
   Server : Sock_Addr_Type;
   Socket : Socket_Type;
   Data   : Socket_Type;
begin
   Server.Addr := ...;
   Server.Port := ...;
   Create_Socket (Socket);
   Bind_Socket (Socket, Server);
   Listen_Socket (Socket);
   loop
      Accept_Socket (Socket, Data, Client);
      -- Start an I/O task, give it Data to communicate over.
      -- Client holds the address of the client. The task will
      -- dispose the socket Data calling Shutdown_Socket and
      -- then Close_Socket on it, when communication is over
   end loop;

> I assume the client opens the socket and the server detects it, then at 
> various times the client makes data requests by sending string data.

That happens later on when the client connects its socket. A client does:

   Create_Socket
   Bind_Socket       -- Client address
   Connect_Socket -- Server address
      -- I/O
   Shutdown_Socket
   Close_Socket

The server listening to a socket gets a new socket when its calls to
Accept_Socket. Accept waits for a client to come. This happens per each
connection, i.e. for each client connection there is one accept completed
on the server side. After accept returned a socket, this socket and the
client's socket are connected, so that when one side writes something into
its socket another side reads that from the socket of its own.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Sockets Example Sought
  2012-11-23 21:58   ` Robert Love
  2012-11-23 22:40     ` Dmitry A. Kazakov
@ 2012-11-23 23:08     ` Simon Wright
  1 sibling, 0 replies; 12+ messages in thread
From: Simon Wright @ 2012-11-23 23:08 UTC (permalink / raw)


Robert Love <rblove@airmail.net> writes:

> On 2012-11-23 18:32:52 +0000, Simon Wright said:
>
>> Robert Love <rblove@airmail.net> writes:
>>
>>> Does anyone have an example of a multi-client server in Ada they
>>> care to share?  It should use the Gnat.Sockets package.  I've seen
>>> samples but they don't seem complete, or at least my understanding
>>> isn't complete<grin>.
>>>
>>> Thanks in advance.
>>
>> task body Server in http://goo.gl/bXVw7 ? (lines 59 .. 143)
>
> What happens at line 120, the else clause on if Server =
> Socket_Server? Is that where data is read in on the socket?
>
> I assume the client opens the socket and the server detects it, then
> at various times the client makes data requests by sending string
> data.

Yes, pretty much. I've added some comments, see the end (these won't
show up via the URL I gave, which is to a specific revision; ).

> The Respond function called just seems to call HTTP.Respond, which is
> not in this file.

Yes. It's in ews-http.ad[sb]; HTTP.Initialize reads the HTTP request,
HTTP.Find works out what sort of response is required, and HTTP.Respond
generates it.

-snippet-

      loop
         declare
            Read_Sockets : GNAT.Sockets.Socket_Set_Type;
            Status : GNAT.Sockets.Selector_Status;
            use type GNAT.Sockets.Selector_Status;
         begin
            --  Initialize Read_Sockets with the sockets in use
            --  (Write_Sockets remains empty, we don't care if a
            --  socket becomes writable; we'll just block in that
            --  case).
            GNAT.Sockets.Copy (Sockets, Read_Sockets);
            --  Wait until something happens on one of the sockets.
            GNAT.Sockets.Check_Selector
              (Selector, Read_Sockets, Write_Sockets, Status);
            if Status = GNAT.Sockets.Completed then
               --  This was a successful completion. Find out which
               --  socket woke us up and deal with it. If there was
               --  more than one, we'll find out next time round the
               --  loop.
               declare
                  Socket : GNAT.Sockets.Socket_Type;
                  use type GNAT.Sockets.Socket_Type;
               begin
                  --  Which socket?
                  GNAT.Sockets.Get (Read_Sockets, Socket);
                  if Socket = Server_Socket then
                     --  It was the server; a new client has called
                     --  connect(). Accept the connection ...
                     GNAT.Sockets.Accept_Socket
                       (Server_Socket, Socket, Address);
                     Trace (Logging_Via, "connection", Socket, Tracing);
                     --  ... and add the new connected socket to the
                     --  set of sockets in use.
                     GNAT.Sockets.Set (Sockets, Socket);
                  elsif Socket = GNAT.Sockets.No_Socket then
                     --  None of our sockets has data/connection
                     --  available; don't care why.
                     Logging_Via ("server got No_Socket", Error);
                  else
                     --  There's an HTTP request to be read on one of
                     --  our connected clients' sockets; deal with it.
                     Trace (Logging_Via, "request", Socket, Tracing);
                     Respond (Socket, Sockets, Logging_Via, Tracing);
                  end if;
               end;
            else
               --  Unexpected, non-fatal error.
               Logging_Via ("server: Check_Selector returned " & Status'Img,
                            Error);
            end if;
            --  Clean up.
            GNAT.Sockets.Empty (Read_Sockets);
         exception
            when E : others =>
               Log (Logging_Via,
                    "server failed in inner loop",
                    With_Exception => E);
         end;
      end loop;



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Sockets Example Sought
  2012-11-23 22:40     ` Dmitry A. Kazakov
@ 2012-11-24 18:27       ` Robert Love
  2012-11-24 21:01         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 12+ messages in thread
From: Robert Love @ 2012-11-24 18:27 UTC (permalink / raw)


The statements about disposing of Data, what does Shutdown_Socket it 
do?  It seems to end my task and never reach the following Close_Socket 
statement.  If I leave it out, I see Close_Socket execute and the 
program seems to run fine.


On 2012-11-23 22:40:59 +0000, Dmitry A. Kazakov said:

> On Fri, 23 Nov 2012 15:58:53 -0600, Robert Love wrote:
> 
>> On 2012-11-23 18:32:52 +0000, Simon Wright said:
>> 
>>> Robert Love <rblove@airmail.net> writes:
>>> 
>>>> Does anyone have an example of a multi-client server in Ada they care
>>>> to share?  It should use the Gnat.Sockets package.  I've seen samples
>>>> but they don't seem complete, or at least my understanding isn't
>>>> complete<grin>.
>>>> 
>>>> Thanks in advance.
>>> 
>>> task body Server in http://goo.gl/bXVw7 ? (lines 59 .. 143)
>> 
>> What happens at line 120, the else clause on if Server = Socket_Server?
>> Is that where data is read in on the socket?
> 
> Socket-select might be a bit difficult to start with. Unless you expect
> hundreds of simultaneous connections, there is a much simpler pattern that
> uses 1-2 tasks (half- or full-duplex I/O) per connection with so-called
> blocking sockets:
> 
>    Client : Sock_Addr_Type;
>    Server : Sock_Addr_Type;
>    Socket : Socket_Type;
>    Data   : Socket_Type;
> begin
>    Server.Addr := ...;
>    Server.Port := ...;
>    Create_Socket (Socket);
>    Bind_Socket (Socket, Server);
>    Listen_Socket (Socket);
>    loop
>       Accept_Socket (Socket, Data, Client);
>       -- Start an I/O task, give it Data to communicate over.
>       -- Client holds the address of the client. The task will
>       -- dispose the socket Data calling Shutdown_Socket and
>       -- then Close_Socket on it, when communication is over
>    end loop;
> 
>> I assume the client opens the socket and the server detects it, then at
>> various times the client makes data requests by sending string data.
> 
> That happens later on when the client connects its socket. A client does:
> 
>    Create_Socket
>    Bind_Socket       -- Client address
>    Connect_Socket -- Server address
>       -- I/O
>    Shutdown_Socket
>    Close_Socket
> 
> The server listening to a socket gets a new socket when its calls to
> Accept_Socket. Accept waits for a client to come. This happens per each
> connection, i.e. for each client connection there is one accept completed
> on the server side. After accept returned a socket, this socket and the
> client's socket are connected, so that when one side writes something into
> its socket another side reads that from the socket of its own.





^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Sockets Example Sought
  2012-11-24 18:27       ` Robert Love
@ 2012-11-24 21:01         ` Dmitry A. Kazakov
  2012-11-27  3:37           ` Robert Love
  0 siblings, 1 reply; 12+ messages in thread
From: Dmitry A. Kazakov @ 2012-11-24 21:01 UTC (permalink / raw)


On Sat, 24 Nov 2012 12:27:04 -0600, Robert Love wrote:

> The statements about disposing of Data, what does Shutdown_Socket it 
> do? It seems to end my task and never reach the following Close_Socket 
> statement.  If I leave it out, I see Close_Socket execute and the 
> program seems to run fine.

Shutdown_Socket does a graceful disconnection before closing the socket. In
particular it flushes/drops pending data. Under Windows it is important to
call it in order to be able to open another socket for the same port.
Otherwise it may take some considerable time after Close_Socket before the
port becomes free. The effect is that you may experience sporadic "port in
use" errors, e.g. when restarting the program.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Sockets Example Sought
  2012-11-24 21:01         ` Dmitry A. Kazakov
@ 2012-11-27  3:37           ` Robert Love
  2012-11-27  8:41             ` Dmitry A. Kazakov
  2012-11-27 15:05             ` Mark Lorenzen
  0 siblings, 2 replies; 12+ messages in thread
From: Robert Love @ 2012-11-27  3:37 UTC (permalink / raw)


On 2012-11-24 21:01:34 +0000, Dmitry A. Kazakov said:

> On Sat, 24 Nov 2012 12:27:04 -0600, Robert Love wrote:
> 
>> The statements about disposing of Data, what does Shutdown_Socket it
>> do? It seems to end my task and never reach the following Close_Socket
>> statement.  If I leave it out, I see Close_Socket execute and the
>> program seems to run fine.
> 
> Shutdown_Socket does a graceful disconnection before closing the socket. In
> particular it flushes/drops pending data. Under Windows it is important to
> call it in order to be able to open another socket for the same port.
> Otherwise it may take some considerable time after Close_Socket before the
> port becomes free. The effect is that you may experience sporadic "port in
> use" errors, e.g. when restarting the program.

BTW, is there an official way to tell when the client closes the 
socket?  When  I'm reading data, I can tell.   If I'm not reading data, 
I can call the Get_Peer(socket) function and catch an exception.  It 
just seems there should be another way?

Thanks for all the advice I've gotten so far.  I'm 95% finished.




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Sockets Example Sought
  2012-11-27  3:37           ` Robert Love
@ 2012-11-27  8:41             ` Dmitry A. Kazakov
  2012-11-27 15:05             ` Mark Lorenzen
  1 sibling, 0 replies; 12+ messages in thread
From: Dmitry A. Kazakov @ 2012-11-27  8:41 UTC (permalink / raw)


On Mon, 26 Nov 2012 21:37:43 -0600, Robert Love wrote:

> BTW, is there an official way to tell when the client closes the 
> socket?

None of the transport's business, which TCP/IP is.

> When  I'm reading data, I can tell.   If I'm not reading data, 
> I can call the Get_Peer(socket) function and catch an exception.  It 
> just seems there should be another way?

Normally there are multiple further layers mounted on the TCP/IP transport
stream, up to the application level. These are usually stateful, and they
may have states corresponding to a desire to disconnect, on either side
depending on the roles the sides play. [Provided, that the protocol is
connection-oriented. There are protocols which are not connection-oriented,
even though using TCP/IP as the transport. For them whether the other side
is gone might be just irrelevant.]

Of course ether side must be prepared to anticipate protocol errors and
connection loss is just one of them. Connection-oriented protocols usually
have corresponding states for this, In such a state the participants would
roll back, one of them would try to restore connection etc.

The bottom line is, usually you would not care actively checking it. Once
you experience an error you react correspondingly. [Keep-alive issues is
another story.]

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Sockets Example Sought
  2012-11-27  3:37           ` Robert Love
  2012-11-27  8:41             ` Dmitry A. Kazakov
@ 2012-11-27 15:05             ` Mark Lorenzen
  1 sibling, 0 replies; 12+ messages in thread
From: Mark Lorenzen @ 2012-11-27 15:05 UTC (permalink / raw)


Den tirsdag den 27. november 2012 04.36.43 UTC+1 skrev Robert Love:
> 
> BTW, is there an official way to tell when the client closes the 
> 
> socket?  When  I'm reading data, I can tell.   If I'm not reading data, 
> 

I think that if you are using a select(2) call AND the select(2) call tells you that there IS data ready for reading, BUT when you try and read some data then there is none, then the connection is closed (aborted).

There is no such thing as proper shutdown using TCP/IP - only a brutal abort.

Regards,

- Mark L



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Sockets Example Sought
  2012-11-23 17:17 Sockets Example Sought Robert Love
  2012-11-23 18:32 ` Simon Wright
@ 2012-11-28  4:43 ` anon
  2012-11-30  5:04   ` Robert Love
  1 sibling, 1 reply; 12+ messages in thread
From: anon @ 2012-11-28  4:43 UTC (permalink / raw)


-- 
--  TCP/IP Echo Service Daemon, based on RFC 342 and RFC 862
--  Normally, a Sender program that accepts a word or quoted
--  sentence from command line is transmitted to the server and
--  the return message is displayed.
-- 
--  This Daemon was tested using "Ada Dual TCP/IP Stacks" using
--  IPv6 and Linux IPv4,
-- 
-- 
--  Protocol: TCP
--  Protocol: UDP not setup at this time.
-- 
--  Usage:    Listener
-- 
--  Tester:   Telnet <hostname>  -port 7
--  Example:  Telnet 127.0.0.1 7
-- 
--  While telnet operational every character including control
--  characters will be echoed
-- 

with Ada.Characters.Latin_9 ;
with Ada.Exceptions ;
with Ada.Text_IO ;
with GNAT.Sockets ;   -- GNAT to reg OS
-- with Sockets ;     -- Ada TCP/IP Stacks

use Ada.Characters.Latin_9 ;
use Ada.Exceptions ;
use Ada.Text_IO ;
use GNAT.Sockets ;
-- use Sockets ;     -- Ada TCP/IP Stacks

procedure Listener is

  --
  --  Operational options
  --
  --  Set to True to use IPv6, But some GNAT.Socket packages, are
  --  not setup to handle IPv6 yet. One way to check is to look at
  --  the body for the "Bind" function. Because the "Bind" function
  --  raises a exception, if IPv6 is use, for those packages that
  --  are IPv4 only.
  --
  IP_V6   : constant Boolean := False ;
  --
  -- Displays a logging message if True
  --
  LOGGING : constant Boolean := False ;

  task type Echo is
    entry Start ( Incoming : Socket_Type ) ;
  end Echo ;

  type Echo_Access is access Echo ;
  type Sock_Addr_Access is access all Sock_Addr_Type ;

  --
  -- Echo -- the main processthat preforms the echo operation
  --      -- one problem is there is no recovery of memory use
  --         by this task once the task ends.
  --

  task body Echo is
      Data     : Character     ;

      Channel  : Stream_Access ;
      Socket   : Socket_Type   ;

    begin
      accept Start ( Incoming : Socket_Type ) do
          Socket := Incoming ;
      end Start ;

      Channel := Stream ( Socket ) ;
      loop
        Data := Character ' Input ( Channel ) ;
        exit when Data = ASCII.Nul ;
        Character ' Output ( Channel, Data ) ;
      end loop ;
      Close_Socket ( Socket ) ;
    exception
      when Socket_Error =>
          Put_Line ( "Connection closed" ) ;
          Close_Socket ( Socket ) ;
    end Echo ;

  --
  Accepting_Socket : Socket_Type ;
  Incoming_Socket  : Socket_Type ;
  Address          : Sock_Addr_Access ;

  Dummy            : Echo_Access ;

  TCP_Error        : exception ;

begin
  --  
  --  Create Socket and sets stacks. With error checking to insure
  --  stacks is valid because some system only have IPv4 and other
  --  have remove IPv4. If both stacks are installed and GNAT
  --  allows both, then use IPv6.
  --
  if IP_V6 then
    begin
      --
      -- set IPv6
      --
      Create_Socket ( Accepting_Socket, Family_Inet6, Socket_Stream ) ;
      Address := new Sock_Addr_Type ( Family_Inet6 );
    exception
      when Socket_Error =>
        Put_Line ( "Error: IP version 6 is not supported" ) ;
        raise TCP_Error ;
    end ;
  else
    begin
      --
      -- set Default IPv4
      --
      Create_Socket ( Accepting_Socket ) ;
      Address := new Sock_Addr_Type ;
    exception
      when Socket_Error =>
        Put_Line ( "Error: IP version 4 is not supported" ) ;
        raise TCP_Error ;
    end ;
  end if ;
  --
  --  Address.Addr is current host can be localhost
  --  Address.Port is 7 based on RFC 342 update RFC 862
  --
  Address.all.Addr := Addresses ( Get_Host_By_Name ( Host_Name ), 1 ) ;
  Address.all.Port := 7 ;
  --
  --  Bind Address to socket
  --
  Bind_Socket ( Accepting_Socket, Address.all ) ;
  --
  --  Set stacks to receive connect events
  --
  Listen_Socket ( Accepting_Socket ) ;
  --
  --  Handle connections
  --
  loop
    --
    --  Wait until client request connect then accept connection
    --
    Accept_Socket ( Accepting_Socket,
                    Incoming_Socket, Address.all ) ;
    --
    --  Log message, if required
    --
    if LOGGING then
      Put ( "Received From: " ) ;
      Put ( Image ( Address.all ) ) ;
    end if ;
    --
    --  Create a single usage task to handle daemon process
    --  task will die once connection is ended.  In this design
    --  there is a possible memory leak because once the task
    --  dies there is no memory recover of the dead task.
    --
    Dummy := new Echo ;
    Dummy.Start ( Incoming_Socket ) ;
  end loop ;

exception
  when TCP_Error =>
      Put_Line ( "Error: Server was not initialized" ) ;

  when others =>
      Put_Line ( "Error: Server is beening shutdown" ) ;
      Shutdown_Socket ( Accepting_Socket, Shut_Read_Write ) ;
end Listener ; 

In <2012112311175432190-rblove@airmailnet>, Robert Love <rblove@airmail.net> writes:
>Does anyone have an example of a multi-client server in Ada they care 
>to share?  It should use the Gnat.Sockets package.  I've seen samples 
>but they don't seem complete, or at least my understanding isn't 
>complete<grin>.
>
>Thanks in advance.
>
>




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Sockets Example Sought
  2012-11-28  4:43 ` anon
@ 2012-11-30  5:04   ` Robert Love
  0 siblings, 0 replies; 12+ messages in thread
From: Robert Love @ 2012-11-30  5:04 UTC (permalink / raw)


Thanks for this.  I will study it.

On 2012-11-28 04:43:47 +0000, anon@att.net said:

> --
> --  TCP/IP Echo Service Daemon, based on RFC 342 and RFC 862
> --  Normally, a Sender program that accepts a word or quoted
> --  sentence from command line is transmitted to the server and
> --  the return message is displayed.
> --
> --  This Daemon was tested using "Ada Dual TCP/IP Stacks" using
> --  IPv6 and Linux IPv4,
> --
> --
> --  Protocol: TCP
> --  Protocol: UDP not setup at this time.
> --
> --  Usage:    Listener
> --
> --  Tester:   Telnet <hostname>  -port 7
> --  Example:  Telnet 127.0.0.1 7
> -- 
> --  While telnet operational every character including control
> --  characters will be echoed





^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2012-12-01  2:48 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-11-23 17:17 Sockets Example Sought Robert Love
2012-11-23 18:32 ` Simon Wright
2012-11-23 21:58   ` Robert Love
2012-11-23 22:40     ` Dmitry A. Kazakov
2012-11-24 18:27       ` Robert Love
2012-11-24 21:01         ` Dmitry A. Kazakov
2012-11-27  3:37           ` Robert Love
2012-11-27  8:41             ` Dmitry A. Kazakov
2012-11-27 15:05             ` Mark Lorenzen
2012-11-23 23:08     ` Simon Wright
2012-11-28  4:43 ` anon
2012-11-30  5:04   ` Robert Love

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox