1 module libsweatyballs.engine.core;
2 
3 import libsweatyballs.router.core : Router;
4 import libsweatyballs.router.table;
5 import libsweatyballs.zwitch.core : Switch;
6 import libsweatyballs.zwitch.neighbor;
7 import libsweatyballs.link.core : Link;
8 import core.sync.mutex : Mutex;
9 import libsweatyballs.engine.configuration : Config;
10 import std.conv : to;
11 import gogga;
12 import core.thread : Thread, dur;
13 import libsweatyballs.router.table : Route;
14 import std.socket : Address, parseAddress;
15 
16 /* TODO: Import for config thing */
17 
18 /**
19 * Engine
20 *
21 * Description: TODO
22 */
23 public final class Engine : Thread
24 {
25     /**
26     * Network components
27     */
28     private Router router;
29     private Switch zwitch;
30 
31     /**
32     * Links the router can advertise over
33     */
34     private Link[] links;
35     private Mutex linksMutex;
36 
37     /**
38     * 1. This must read config given to it
39     * 2. Setups links
40     * 3. Create new Router with these links
41     * 4. Spawn a Switch that handles packet in/out
42     * 5. Pass the Switch the router
43     * 6. Start the switch
44     * 7. We must then mainloop and collect statistics and handle shutdown etc
45     */
46     this(Config config)
47     {
48         /* TODO: Add comment */
49         super(&worker);
50 
51         /* TODO: Read config */
52         parseConfig(config);
53 
54         /* Initialize locks */
55         initMutexes();
56     }
57 
58     /**
59     * Initializes all the mutexes
60     */
61     private void initMutexes()
62     {
63         linksMutex = new Mutex();
64     }
65 
66     public Link[] getLinks()
67     {
68         Link[] copy;
69 
70         linksMutex.lock();
71         foreach(Link link; links)
72         {
73             copy ~= link;
74         }
75         linksMutex.unlock();
76 
77         return copy;
78     }
79 
80     private void parseConfig(Config config)
81     {
82         /* TODO: Set configuration parameter */
83 
84         /* Setup links */
85         links = createLinks(config.links);
86         setupLinks(links);
87 
88         /**
89         * Setup a new Router
90         */
91         router = new Router(this, config.routerIdentity);
92         
93         
94         
95 
96         /* Setup a new Switch */
97         zwitch = new Switch(this);
98 
99         /* Add self neighbor to any link (try the first, TODO: Atleast one link is needed) */
100         Address address = parseAddress("::", links[0].getR2RPort());
101         Neighbor selfNeighbor = new Neighbor(router.getIdentity().getKeys().publicKey, address, links[0]);
102 
103 
104         Route route = new Route(router.getIdentity().getKeys().publicKey, selfNeighbor);
105         route.setAgeibility(false);
106 
107         router.getTable().addRoute(route);
108         
109     }
110 
111     public Router getRouter()
112     {
113         return router;
114     }
115 
116     public Switch getSwitch()
117     {
118         return zwitch;
119     }
120 
121     private void worker()
122     {
123         while(true)
124         {
125             /**
126             * FIXME: Remove this, this is just testing code
127             */
128             Route[] routes = router.getTable().getRoutes();
129             foreach(Route route; routes)
130             {
131                 zwitch.sendPacket(route.getAddress(), cast(byte[])"Hello world");    
132             }
133 
134             Thread.sleep(dur!("seconds")(1));
135         }
136     }
137 
138     private Link[] createLinks(string[] interfaces)
139     {
140         Link[] createdLinks;
141 
142         foreach(string interfaceName; interfaces)
143         {
144             createdLinks ~= new Link(interfaceName, this);
145         }
146 
147         return createdLinks;
148     }
149 
150     private void setupLinks(Link[] links)
151     {
152         gprintln("Begin link initailization");
153         foreach(Link link; links)
154         {
155             gprintln("Initializing link "~to!(string)(link)~" ...");
156             link.launch();
157         }
158         gprintln("Links have been initialized");
159     }
160 
161     public void launch()
162     {
163         /* Start the engine */
164         start();
165 
166         /* Start router */
167         router.launch();
168 
169         /* Start switch */
170         zwitch.launch();
171 
172         /* Start collector */
173         /* TODO: Add me */
174 
175         gprintln("Engine has started all threads and is now going to finish and return to constructor thread control");
176     }
177 }