MODULE CommObxStreamsServer;

   project   = "BlackBox"
   organization   = ""
   contributors   = "Oberon microsystems"
   version   = "System/Rsrc/About"
   copyright   = "System/Rsrc/About"
   license   = "Docu/BB-License"
   changes   = ""
   issues   = ""


   IMPORT Services, CommStreams, Views, TextModels, TextViews, StdLog;


      protocol = "CommTCP";         (* driver for TCP/IP communication, over Winsock *)
      localAdr = "900";               (* this is the port on which the server listens *)

      Server = POINTER TO RECORD (Services.Action)
         listener: CommStreams.Listener   (* the server listens using this object and accepts incoming connections*)
      Processor = POINTER TO RECORD (Services.Action)

         prev, succ: Processor;   (* linked to allow stopping of all active processors with Stop command *)
         stream: CommStreams.Stream;   (* for each connection, a receiver communicates through this object *)
         writer: TextModels.Writer

      server: Server;
      processors: Processor;
   PROCEDURE (server: Server) Do;

      VAR s: CommStreams.Stream; p: Processor; t: TextModels.Model;
      server.listener.Accept(s);   (* poll for a connection *)
      IF s # NIL THEN   (* upon accept create and start processor for new connection *)
         NEW(p); p.prev := NIL; p.succ := processors; processors := p;
         IF p.succ # NIL THEN p.succ.prev := p END; := s;
         t := TextModels.dir.New(); p.writer := t.NewWriter(NIL);
         Views.OpenAux(TextViews.dir.New(t), "Message");
   END Do;
   PROCEDURE (p: Processor) Do;

      VAR buf: ARRAY 256 OF BYTE; read, i: INTEGER;
   BEGIN, 0, LEN(buf), read);   (* poll for incoming data *)
      IF read > 0 THEN   (* write received data into log *)
         i := 0; WHILE i # read DO p.writer.WriteChar(CHR(buf[i])); INC(i) END;
         IF p.prev # NIL THEN p.prev.succ := p.succ ELSE processors := p.succ END;
         IF p.succ # NIL THEN p.succ.prev := p.prev END
   END Do;
   PROCEDURE Start*;

      VAR l: CommStreams.Listener; res: INTEGER;
      IF server = NIL THEN
         CommStreams.NewListener(protocol, localAdr, l, res);
         IF l # NIL THEN
            NEW(server); server.listener := l; Services.DoLater(server,;
            StdLog.String("server: server started"); StdLog.Ln
            StdLog.String("server: error starting the server ("); StdLog.Int(res); StdLog.Char(")"); StdLog.Ln
   END Start;

      WHILE processors # NIL DO; Services.RemoveAction(processors);
         processors := processors.succ
      IF server # NIL THEN
         server := NIL;
         StdLog.String("server: server stopped"); StdLog.Ln
   END Stop;

   Stop   (* prevent the server from trapping after module unloading *)
END CommObxStreamsServer.