summaryrefslogtreecommitdiff
path: root/system/net/1.8.7/src/net manager
blob: 05f530ecb5410eb541b19b59944a5d9140be6cd1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
PACKET net manager DEFINES stop,net manager,frei, routen aufbauen, 
 (*   175 net manager   8 (!)   *)
                           start,
                           definiere netz,
                           aktiviere netz,
                           list option,
                           erlaube, sperre, starte kanal, routen: 
 
TEXT VAR stand := "Netzsoftware vom  10.06.87  "; 
                 (*Heinrichs     *)           
LET
    maxstat = 127,
    ack = 0,
(*  nak = 1, *)
    error nak = 2,
(*  zeichen eingang = 4, *)
    list code = 15,
(*  fetch code = 11, *)
    freigabecode = 29,
    tabellencode = 500,
    continue code = 100,
    erase code = 14,
    report code = 99, 
    abgleichcode = 98,
    neue routen code = 97,
    dr verwaltungslaenge = 8,

    (* Codes der Verbindungsebene *) 
 
    task id code = 6, 
    name code = 7, 
    task info code = 8, 
    routen liefern code = 9, 
 
    (* Weitergabecodes für Netzknoten *)

    route code = 1001,
    out code = 1003,

    (* Typen von Kommunikationsströmen *)

    zustellung = 1,
    call im wait = 3,
    call im abbruch = 4, 
    call in zustellung = 5;

LET STEUER =
      STRUCT ( 
      INT  head, 
           zwischenziel,
           zielrechner, 
           quellrechner,
           strom,
      INT  sequenz,
           seiten nummer,
      TASK quelle,ziel,
      INT  sende code); 
 
LET INFO = STRUCT (STEUER steuer, INT typ,maxseq); 
 
LET PARA = STRUCT (TASK quelle, ziel, INT sendecode, zielstation); 
 
 
TASK VAR sohn;
INT VAR strom,c,kanalmode, rzaehler := 20;
BOUND STRUCT (ROW maxstat INT port, 
              ROW maxstat INT zwischen)  VAR route;
 
  
TASK PROC netport (INT CONST ziel): 
   INT VAR kan := route.port (ziel) AND 255; 
   IF kan < 1 OR kan > 15
   THEN 
     niltask 
   ELSE 
     IF NOT exists (nettask (kan)) 
     THEN 
       access catalogue;
       nettask (kan) := task (kan); 
       IF NOT (nettask (kan) < father) THEN nettask (kan) := niltask FI; 
     FI; 
     nettask (kan) 
   FI
END PROC netport; 
 
PROC frei (INT CONST stat,lvl): 
  DATASPACE VAR ds := nilspace;
  BOUND STRUCT (INT x,y) VAR msg := ds;
  msg.x := stat; msg.y := lvl;
  INT VAR return;
  call (netport (stat), freigabecode, ds, return) ;
  forget (ds)
END PROC frei; 
 
PROC net manager (DATASPACE VAR ds, INT CONST order, phase, TASK CONST
                  ordertask):
 
    IF order = report code AND ordertask < myself
    THEN 
      IF storage (old("report")) > 20 THEN forget ("report", quiet) FI;
      FILE VAR rp := sequential file (output, "report");
      BOUND TEXT VAR rpt := ds;
      putline (rp, rpt);
      send (ordertask, ack, ds)
    ELIF order = abgleichcode AND ordertask < myself
    THEN  
      BOUND STRUCT (INT ende, zwischen) VAR x := ds; 
      route.port (x.ende) := channel (ordertask);
      route.zwischen (x.ende) := x.zwischen;
      send (ordertask, ack, ds)
    ELIF order = neue routen code AND ordertask < myself
    THEN
      forget ("port intern");
      copy (ds,"port intern");
      route := old ("port intern");
      send (ordertask, ack, ds)
    ELIF station (ordertask) = station (myself)
    THEN
      IF ordertask < myself
      OR order = list code
      OR order > continue code
      THEN
        IF order = list code 
        THEN
          enable stop;
          forget (ds); ds := old ("report");
          FILE VAR ff := sequential file (output,ds);
          putline (ff,"bekannte Stationen:");
          stationen; line (ff); putline (ff,"--------");
          putline (ff,"Eingestellte Netzmodi:"); 
          kanaele ; 
          paketgroessen; 
          line (ff); putline (ff,"********"); 
          putline (ff,stand);
          putline (ff,"Rechner "+text(station(myself))+"  um "+time of day);
          send (ordertask, ack, ds)
        ELSE
        free manager (ds,order,phase,order task) 
        FI
      ELSE
      errorstop ("nur 'list' ist erlaubt")
      FI
    FI .
  
stationen: 
INT VAR stat; 
INT VAR mystation := station (myself);
FOR stat FROM 1 UPTO maxstat REP 
  IF route.port (stat) > 0 AND stat <> mystation 
  THEN 
    put (ff,text(stat)+"("+text (route.port (stat) AND 255)+","+
    text(route.zwischen(stat))+")") 
  FI 
PER. 
 
paketgroessen: 
 
  line(ff); 
  put (ff, "Nutzlaenge bei indirekter Verbindung "+ 
           text (data length via node) + " Byte "); line (ff). 
 
kanaele: 
   INT VAR portnummer; 
   TASK VAR tsk; 
   FOR portnummer FROM 1 UPTO 15 REP 
      tsk := task (portnummer);
      IF tsk < myself THEN beschreibe kanal FI; 
   PER. 
 
beschreibe kanal: 
   putline (ff, name (tsk) + " haengt an Kanal " + text (channel (tsk))
                + ", " + mode text (netz mode (portnummer))).
 
END PROC net manager; 

TASK VAR cd,stask;
ROW maxstat INT VAR erlaubt; 

PROC communicate: 
  enable stop;
  INT VAR scode, merken :=0;
  DATASPACE VAR dr := nilspace;
  neuer start (quit max, kanalmode); 
REP 
  forget (dr); 
  telegrammfreigabe; 
  wait (dr, scode, stask); 
  cd := collected destination;
  IF weiterleitung steht noch aus
  THEN 
    send (netport (merken), out code, mds, reply); 
    IF reply <> -2 THEN forget (mds); merken := 0 FI 
  FI;
  IF zeichen da OR zeit abgelaufen 
  THEN 
    packet
  ELIF cd = myself 
  THEN 
    netz info und steuerung 
  ELSE
    sendung untersuchen (stask, cd, scode, dr)
  FI 
PER. 
 
telegrammfreigabe: 
   INT VAR dummy; 
   control (22,0,0,dummy). 
 
zeichen da: scode < 0 . 
 
zeit abgelaufen: scode = ack AND cd = myself. 

packet: 
    INT VAR snr, ant,err;
    TASK VAR quelle, ziel;
    snr := 0;
    IF NOT zeichen da THEN routen erneuern FI;
    REP 
      IF NOT zeichen da
      THEN 
        forget (dr);
        zeitueberwachung (snr, quelle, ziel, ant, dr); 
      ELIF NOT weiterleitung steht noch aus
      THEN
        packet eingang (snr, quelle, ziel, ant, dr); 
      FI;
      IF snr = 1000
      THEN
        packet weiterleiten
      ELIF snr > 0
      THEN 
        IF ant > 6 AND erlaubt(station (quelle)) < 0 
        THEN unerlaubt
        ELSE
          send (quelle,ziel,ant,dr,err); 
          fehlerbehandlung ;
        FI
      FI 
    UNTIL snr = 0 OR zeichen da PER.
 
routen erneuern: 
  rzaehler DECR 1; 
  IF rzaehler = 0 
  THEN 
    rzaehler := 20; 
    neue routen holen
  FI. 

weiterleitung steht noch aus: merken <> 0. 
 
packet weiterleiten: 
  INT VAR reply;
  IF NOT ((route.port (ant) AND 255) = channel OR route.port (ant) < 0)
  THEN 
    send (netport (ant), out code, dr, reply);
    IF reply = -2 
    THEN
      merken := ant; 
      DATASPACE VAR mds := dr 
    FI
  ELSE
    report ("Weiterleitung nicht möglich für "+text(ant)) 
  FI.

fehlerbehandlung: 
  IF ok oder ziel nicht da THEN loesche verbindung (snr) FI. 
 
ok oder ziel nicht da: err=0 OR err=-1. 

netz info und steuerung: 
    IF scode = list code THEN   list status 
  ELIF scode = erase code THEN strom beenden
  ELIF scode = freigabe code AND stask = father THEN freigabelevel 
  ELIF scode >= route code THEN weitergaben
  ELIF scode > tabellencode THEN routen ausliefern
  ELSE forget (dr); ablehnen ("nicht möglich") 
  FI. 
  
weitergaben: 
  IF stask < father
  THEN 
    IF scode = out code 
    THEN 
      BOUND INT VAR stx lng := dr; 
      INT VAR decoded lng := stx lng; 
      decode packet length (decoded lng); 
      transmit header (dr); 
      blockout (dr,1,drverwaltungslaenge,decoded lng); 
      transmit trailer  
    ELIF scode = route code 
    THEN 
      BOUND PARA VAR parah := dr; 
      PARA VAR para := parah; 
      pingpong (stask, ack, dr, reply); 
      neue sendung (para.quelle, para.ziel, para.sendecode, 
                    para.zielstation, dr); 
      forget (dr); dr := nilspace; 
      send (stask, ack, dr) 
    FI
  ELSE 
    forget (dr); 
    ablehnen ("nicht Sohn von "+name(father)) 
  FI. 
  
routen ausliefern: 
  neue sendung (stask, myself, -routen liefern code, scode-tabellencode,dr). 
  
freigabelevel: 
  BOUND STRUCT (INT stat,lvl) VAR lv := dr; 
  IF lv.stat > 0 AND lv.stat <= maxstat THEN erlaubt (lv.stat) := lv.lvl FI; 
  send (stask,ack,dr). 
 
unerlaubt: 
  report ("Fremdzugriff von "+text(station (quelle))+" auf "+nam(ziel)
          +" code "+text(ant)); 
  loesche verbindung (snr);
  forget (dr); dr := nilspace;
  BOUND TEXT VAR errtxt := dr; 
  errtxt:="Kein Zugriff auf Station "+text (station (myself)); 
  neue sendung (ziel, quelle, error nak, station (quelle), dr). 
 
strom beenden:
  BOUND TEXT VAR stromtext := dr;
  INT VAR erase strom := int (stromtext);
  forget (dr);
  strom := erase strom;
  IF falsche stromnummer THEN ablehnen ("Strom gibt es nicht")
  ELSE 
    BOUND INFO VAR v := verbindung (strom); 
  IF
    stask < supervisor OR stask = vx.quelle OR stask = vx.ziel
  THEN
    loeschen
  ELSE ablehnen ("Nur Empfänger/Absender darf löschen")
  FI
  FI. 
 
loeschen:
  IF sendeeintrag  THEN
    IF callee (vx.quelle) = vx.ziel THEN absender warnen FI;
    loesche verbindung (strom)
  ELSE
    IF callee (vx.ziel) = vx.quelle THEN warnen FI; 
    loesche verbindung (strom)
  FI; 
  dr := nilspace;
  send (stask,ack,dr).

absender warnen:
 dr := nilspace;
 send(vx.ziel,vx.quelle,1,dr,err) .
 
warnen:
 dr := nilspace;
errtxt := dr; errtxt:= "Station antwortet nicht"; 
send (vx.quelle,vx.ziel,error nak, dr, err). 
 
falsche stromnummer: strom < 1 OR strom > max verbindungsnummer.
sendeeintrag: vx.quellrechner = station (myself).
vx: v.steuer.
END PROC communicate; 
 
PROC list option: 
  begin ("net list",PROC list net, sohn) 
END PROC list option; 
 
PROC list net: 
  disable stop;
  DATASPACE VAR ds ;
  INT VAR scode;
  REP
    wait (ds, scode, stask); 
    forget (ds); ds := nilspace;
    FILE VAR f := sequential file (output, ds); 
    list (f, father);
    list netports; 
    IF is error THEN clear error; 
                     forget(ds); 
                     ds := nilspace; 
                     f := sequential file (output, ds); 
                     output (f); putline (f,errormessage); 
                     clear error 
    FI; 
    send (stask, ack, ds) 
  PER. 
 
list netports: 
  INT VAR k; 
  FOR k FROM 1 UPTO 15 REP
    TASK VAR tsk := task (k); 
    IF tsk < father  
    THEN 
      putline (f, name (tsk)); 
      list (f,tsk) 
    FI 
  PER. 
 
END PROC list net; 
 
PROC neue routen holen: 
    forget ("port intern", quiet); 
    fetch ("port intern"); 
    route := old ("port intern"); 
    neue routen
END PROC neue routen holen; 
 
PROC sendung untersuchen (TASK CONST q, z, INT CONST cod, DATASPACE VAR dr): 
  IF z = collector 
  THEN 
    verbindungsebene 
  ELIF station (z) <> 0
  THEN
    sendung (q,z,cod,station (z),dr)
  ELSE
    ablehnen ("Station 0")
  FI.

verbindungsebene: 
  IF cod = 256 THEN name von fremdstation
  ELIF cod > 256
  THEN
    taskinfo fremd 
  ELIF callee (q) = z  (* gegen errornak an collector *)
  THEN
    task id von fremd
  FI.

taskinfo fremd: sendung  (q, collector,  -task info code,cod-256,dr).

task id von fremd: sendung  (q, collector, -task id code, zielstation, dr) .

name von fremdstation:
  BOUND TASK VAR tsk := dr;
  TASK VAR tsk1 := tsk;
  forget (dr); 
  dr := nilspace; 
  sendung  (q, tsk1, -name code, station (tsk1), dr).

zielstation: cod.
END PROC sendung untersuchen;

PROC sendung (TASK CONST q, z, INT CONST code, z stat, DATASPACE VAR dr):
  IF z stat < 1 OR z stat > maxstat
  THEN
    ablehnen ("ungültige Stationsnummer");
    LEAVE sendung
  FI;
  INT VAR reply;
  INT VAR rp := route.port (z stat) AND 255;
  IF rp = 255 THEN neue routen holen ;rp := route.port (z stat) AND 255 FI;
  IF rp = channel
  THEN
     sendung selbst betreiben
  ELIF rp > 0 AND rp < 16
  THEN
     sendung weitergeben
  ELSE
     ablehnen ("Station "+text(z stat)+" gibt es nicht")
  FI.

sendung selbst betreiben:
  neue sendung (q, z, code, z stat, dr). 

sendung weitergeben:
  DATASPACE VAR ds := nilspace;
  BOUND PARA VAR p := ds;
  p.quelle := q;
  p.ziel := z;
  p.zielstation := z stat;
  p.sendecode := code;
  call (netport (z stat), route code, ds, reply);
  forget (ds);
  pingpong (netport (z stat), 0, dr, reply);
  forget (dr);
  IF reply < 0 THEN ablehnen ("netport "+text(route.port(zstat)AND255)
                    + " fehlt") FI
END PROC sendung; 

PROC ablehnen (TEXT CONST t):
  DATASPACE VAR vdr := nilspace;
  BOUND TEXT VAR errtxt := vdr; 
  INT VAR err;
  errtxt := t;
  send (cd,stask, error nak, vdr,err);
  forget (vdr).
END PROC ablehnen;

PROC stop: 
  access catalogue;
  IF exists task ("net timer") 
  THEN 
    TASK VAR nets := father (/"net timer"); 
  ELSE
    nets := myself
  FI; 
  nets := son (nets);
  WHILE NOT (nets = niltask) REP 
    IF text (name (nets),3) = "net" OR name (nets) = "router" 
    THEN
      end (nets) 
    FI; 
    nets := brother (nets)
  PER 
END PROC stop; 
 
PROC list status: 
 
  DATASPACE VAR ds := nilspace; 
  FILE VAR f:=sequential file (output, ds);
  line(f); 
  FOR strom FROM 1 UPTO max verbindungsnummer REP 
    IF strom > 0 THEN 
    BOUND INFO VAR v := verbindung (strom);
    IF vx.strom <> 0 THEN info FI 
    FI; 
  PER; 
  send (stask, ack, ds). 
 
info: 
  put (f,"Strom "+text(strom));
  put (f,"(sqnr"+text(vx.sequenz)+"/"+text (v.maxseq)+")"); 
  IF sendeeintrag THEN sendeinfo ELSE empfangsinfo FI; 
  line (f). 
 
sendeeintrag: vx.quellrechner = station(myself) . 
 
sendeinfo: 
  IF v.typ = call im wait THEN put (f,"erwartet Antwort von")
  ELIF v.typ = call in zustellung THEN put (f,"Ziel busy. Zielstation:") 
  ELIF v.typ = call im abbruch THEN put (f,"wird gelöscht bei Antwort von") 
  ELSE put (f,"sendet an") 
  FI; 
  put (f,vx.zielrechner); 
  put (f,". Absender ist """+nam (vx.quelle)+"""."). 
 
empfangsinfo: 
  IF v.typ = zustellung THEN 
  put (f,"Sendung noch nicht zustellbar")
  ELSE
  put (f,"empfängt von");
  put (f,vx.quellrechner); 
  FI;
  put (f,". Empfaenger ist """+nam (vx.ziel)+""".").

vx: v.steuer.
END PROC list status; 
 
INT VAR quitmax := 3;

ROW 15 TASK VAR net task;  
ROW 15 INT VAR netz mode; 

PROC erlaube (INT CONST von, bis):
  IF ein kanal gestartet
  THEN
    putline ("Warnung: 'erlaube' muß vor 'starte kanal'")
  FI;
  test (von); test (bis);
  INT VAR i;
  FOR i FROM von UPTO bis REP erlaubt (i) := 0 PER 
END PROC erlaube;

PROC sperre  (INT CONST von, bis):
  IF ein kanal gestartet
  THEN
    putline ("Warnung: 'sperre' muß vor 'starte kanal'")
  FI;
  test (von); test (bis);
  INT VAR i;
  FOR i FROM von UPTO bis REP erlaubt (i) :=-1 PER 
END PROC sperre ;

BOOL VAR  alte routen, ein kanal gestartet; 
 
PROC definiere netz: 
  stop;
  INT VAR i;
  FOR i FROM 1 UPTO 15 REP net task (i) := niltask PER; 
  ein kanal gestartet := FALSE;
  FILE VAR s := sequential file (output,"report"); 
  putline (s," N e u e r   S t a r t " + date + " " + time of day ); 
  alte routen := exists ("port intern");
  IF alte routen
  THEN
    route := old ("port intern")
  ELSE
    route := new ("port intern"); 
    initialize routes
  FI. 
 
  initialize routes: 
     FOR i FROM 1 UPTO maxstat REP 
        route.zwischen(i) := i 
     PER. 
 
END PROC definiere netz; 
 
PROC starte kanal (INT CONST k,modus,stroeme): 
  ein kanal gestartet := TRUE;
  IF exists (canal (k)) THEN end (canal (k)) FI;
  IF stroeme <= 0 THEN errorstop ("3.Parameter negativ") FI; 
  quitmax := stroeme;
  c := k; 
  IF c < 1 OR c > 15 THEN errorstop ("unzulässiger Kanal:"+text(c)) FI; 
  kanalmode := modus; 
  IF kanalmode < 1 OR kanalmode > max mode 
        THEN errorstop ("unzulässiger Netzbetriebsmodus:"+text(kanalmode)) 
        ELSE netz mode (c) := kanalmode 
  FI; 
  IF NOT exists task ("net port") 
  THEN
    begin ("net port",PROC net io, net task (c));
    define collector (/"net port")
  ELSE 
    begin ("net port "+text (c),PROC net io, net task (c))
  FI. 
END PROC starte kanal;

PROC routen (INT CONST von, bis, kanal, zw): 
  INT VAR i;
  IF kanal < 0 OR kanal > 15 THEN errorstop ("Kanal unzulässig") FI;
  test (von); test (bis); 
  FOR i FROM von UPTO bis REP 
      route.port (i) := kanal+256; 
      IF zw=0
      THEN 
        route.zwischen (i) := i  
      ELSE 
        test (zw);
        route.zwischen (i) := zw
      FI 
  PER. 
END PROC routen; 
 
PROC routen (INT CONST von, bis, kanal): 
  routen (von, bis, kanal, 0) 
END PROC routen;

PROC test (INT CONST station): 
  IF station < 1 OR station > maxstat 
  THEN 
    errorstop (text (station) + " als Stationsnummer unzulässig") 
  FI 
END PROC test; 
 
PROC aktiviere netz: 
vorgegebene routen pruefen; 
IF existstask ("net timer") THEN end (/"net timer") FI;
begin ("net timer",PROC timer,sohn);
IF NOT alte routen 
THEN 
  routen aufbauen
ELSE
  IF online THEN break FI
FI. 

vorgegebene routen pruefen: 
  INT VAR i; 
  FOR i FROM 1 UPTO maxstat REP 
    INT VAR s := route.port (i) AND 255; 
    IF s > 0 AND s <= 15 CAND nettask (s) = niltask 
    THEN 
      errorstop ("Kanal "+text(s)+" nicht gestartet, steht aber in Routen") 
    FI 
  PER.
END PROC aktiviere netz; 
 
 
PROC routen aufbauen: 
  alte routen := TRUE;
  c := channel;
  break (quiet);
  begin ("router", PROC rout0, sohn). 
END PROC routen aufbauen; 
 
PROC rout0: 
  disable stop; 
  rout; 
  IF is error 
  THEN 
    put error 
  FI; 
  end (myself) 
END PROC rout0; 
 
PROC rout:
  IF c>0 THEN continue (c) FI;
  clear error;   enable stop;
  fetch ("port intern");
  route := old ("port intern"); 
  routen aufbauen;
  ds := old ("port intern");
  call (father, neue routen code, ds, reply). 
 
routen aufbauen:
  access catalogue; 
  TASK VAR port := brother (myself); 
  WHILE NOT (port = niltask) REP 
    IF text (name (port),8) = "net port" THEN nachbarn FI; 
    port := brother (port) 
  PER; 
  IF online THEN putline ("Fertig. Weiter mit SV !") FI. 

aenderbar: route.port (st) < 256.

nachbarn:  
  INT VAR st,reply; 
  FOR st FROM 1 UPTO maxstat REP 
    IF erlaubt (st) >= 0 AND st <> station (myself) AND aenderbar
    THEN 
      IF online THEN put (name (port)); put (st) FI;
      DATASPACE VAR ds := nilspace; 
        call (port, tabellencode+st, ds, reply);
        IF reply = ack 
        THEN 
          BOUND STRUCT (ROW maxstat INT port, 
                        ROW maxstat INT zwischen)  VAR fremd := ds; 
          route.port (st) := channel(port); 
          route.zwischen (st) := st; 
          indirekte ziele 
        ELIF reply < 0
        THEN
          errorstop ("netz läuft nicht (Kanalnummer falsch)")
        ELSE 
          BOUND TEXT VAR xt := ds;
          IF online THEN put (xt) FI;
        FI;
      IF online THEN line FI;
      forget (ds) 
    FI
  PER. 
 
indirekte ziele:   
  INT VAR kanal := fremd.port (station (myself)) AND 255;
  INT VAR ind; 
  FOR ind FROM 1 UPTO maxstat REP 
    IF ind bei st bekannt AND NOT ((fremd.port (ind) AND 255) = kanal)
      AND route.port (ind) < 256
    THEN 
      route.port (ind) := channel (port); 
      route.zwischen (ind) := st 
    FI 
  PER.
 
ind bei st bekannt: NOT (fremd.port (ind) = -1).
 
END PROC rout;


PROC timer: 
  disable stop;
  access catalogue;
  INT VAR old session := 1;
  REP 
    IF session <> old session
    THEN
      define collector (/"net port");
      old session := session
    FI;
    clear error;
    pause (30); 
    sende tick an alle ports 
  PER.
 
sende tick an alle ports :
  TASK VAR fb := son (father); 
  REP 
   IF NOT exists (fb) THEN access catalogue;LEAVE sende tick an alle portsFI;
   IF channel (fb) > 0
   THEN 
     DATASPACE VAR ds := nilspace;
     send (fb, ack, ds); 
     pause (10)
   FI;
   fb := brother (fb) 
  UNTIL fb = niltask PER. 
 
END PROC timer; 

PROC net io:
  disable stop; 
  set net mode (kanalmode); 
  fetch ("port intern"); 
  route := old ("port intern");
  commanddialogue (FALSE); 
  continue (c);
  communicate;
  TEXT VAR emsg := "++++++ "+error message +" Zeile "+text(errorline);
  clear error; 
  report (emsg);
  end (myself) 
END PROC net io; 
 
PROC start: run ("netz") END PROC start; 
 
END PACKET net manager;