1use std::collections::{HashMap, VecDeque};
7use std::env::args;
8use std::mem;
9use std::sync::{Arc, Mutex, atomic};
10
11use haiku_sys::{thread_info, thread_id, find_thread, get_thread_info, port_id, team_id};
12
13use ::app::{Handler, Message, Messenger};
14use ::app::looper::{HandlerType, Looper, LooperDelegate, NEXT_HANDLER_TOKEN};
15use ::app::roster::{ROSTER, ApplicationRegistrationStatus};
16use ::app::serverlink::{ServerLink, server_protocol};
17use ::app::sys::{B_ARGV_RECEIVED, B_READY_TO_RUN, B_QUIT_REQUESTED, QUIT, B_PREFERRED_TOKEN, get_app_path};
18use ::kernel::INFINITE_TIMEOUT;
19use ::kernel::ports::Port;
20use ::storage::MimeType;
21use ::storage::sys::entry_ref;
22use ::support::Result;
23
24const LOOPER_PORT_DEFAULT_CAPACITY: i32 = 200;
25
26pub struct Application<A> where A: ApplicationHooks + Send + 'static {
38 state: Arc<Mutex<A>>,
39 inner_looper: Looper<A>,
40 link: ServerLink
41}
42
43impl<A> Application<A> where A: ApplicationHooks + Send + 'static {
44 pub fn new(signature: &str, initial_state: A) -> Self {
57 let mime_type = match MimeType::new(signature) {
59 Some(t) => t,
60 None => panic!("Invalid MimeType")
61 };
62
63 if mime_type.is_supertype_only() || (mime_type.get_supertype() != MimeType::new("application").unwrap()) {
64 panic!("Invalid MimeType");
65 }
66
67 let path = get_app_path(0).expect("Cannot get the path for this executable");
69 let entry = entry_ref::from_path(&path).expect("Cannot get the entry_ref for this executable");
70
71 let app_flags: u32 = 1; let port = Port::create("application", LOOPER_PORT_DEFAULT_CAPACITY).unwrap();
76 let (team, thread) = get_current_team_and_thread();
77 let registration = match ROSTER.is_application_registered(&entry, team, 0) {
78 Ok(r) => r,
79 Err(_) => panic!("Error communicating with the registrar about the registration status")
80 };
81 match registration {
82 ApplicationRegistrationStatus::Registered(_) => (), ApplicationRegistrationStatus::PreRegistered(_) => panic!("Pre registered applications are not implemented"),
84 ApplicationRegistrationStatus::NotRegistered => (), };
86
87 match ROSTER.add_application(&String::from(signature), &entry, app_flags,
88 team, thread, port.get_port_id(), true) {
89 Ok(_) => (),
90 Err(_) => panic!("Error registering with the registrar")
91 };
92
93 let state = Arc::new(Mutex::new(initial_state));
95 let default_looper_state = Box::new(ApplicationLooperState{});
96 let context = Context {
97 handler_messenger: Messenger::from_port(&port).unwrap(),
98 looper: LooperDelegate{ messenger: Messenger::from_port(&port).unwrap() },
99 application: ApplicationDelegate{ messenger: Messenger::from_port(&port).unwrap() },
100 application_state: state.clone()
101 };
102 let mut handlers = HashMap::new();
103 let handler_token = NEXT_HANDLER_TOKEN.fetch_add(1, atomic::Ordering::Relaxed);
104 handlers.insert(handler_token, HandlerType::LooperState);
105 let mut inner_looper = Looper {
106 name: String::from("application"),
107 port: port,
108 message_queue: VecDeque::new(),
109 handlers: handlers,
110 preferred_handler: handler_token,
111 context: context,
112 state: default_looper_state,
113 terminating: false
114 };
115
116 let mut argv_message = Message::new(B_ARGV_RECEIVED);
118 argv_message.header.target = B_PREFERRED_TOKEN;
119 argv_message.add_data("_internal", &true).unwrap();
120 inner_looper.message_queue.push_back(argv_message);
121
122 let mut ready_message = Message::new(B_READY_TO_RUN);
124 ready_message.header.target = B_PREFERRED_TOKEN;
125 inner_looper.message_queue.push_back(ready_message);
126
127 let mut link = ServerLink::create_desktop_connection().unwrap();
129 link.sender.start_message(server_protocol::AS_CREATE_APP, 0).unwrap();
136 link.sender.attach(&link.receiver.port.get_port_id()).unwrap();
137 link.sender.attach(&inner_looper.port.get_port_id()).unwrap();
138 link.sender.attach(&team).unwrap();
139 link.sender.attach(&handler_token).unwrap();
140 link.sender.attach_string(signature).unwrap();
141 link.sender.flush(true).unwrap();
142 let message = link.receiver.get_next_message(INFINITE_TIMEOUT).unwrap();
143 if message.0 != 0 {
144 panic!("Cannot register the application at the app_server");
145 }
146 let server_port: port_id = link.receiver.read(0).unwrap();
147 let _: i32 = link.receiver.read(0).unwrap(); let _: i32 = link.receiver.read(0).unwrap(); link.sender.set_port(Port::from_id(server_port).unwrap());
150
151 Self {
152 state: state,
153 inner_looper: inner_looper,
154 link: link
155 }
156 }
157
158 pub fn create_looper(&mut self, name: &str, initial_state: Box<dyn Handler<A> + Send>) -> Looper<A>
169 {
170 let port = Port::create(name, LOOPER_PORT_DEFAULT_CAPACITY).unwrap();
171 let mut handlers = HashMap::new();
172 let token = NEXT_HANDLER_TOKEN.fetch_add(1, atomic::Ordering::Relaxed);
173 handlers.insert(token, HandlerType::LooperState);
174 let context = Context {
175 handler_messenger: Messenger::from_port(&port).unwrap(),
176 looper: LooperDelegate{ messenger: Messenger::from_port(&port).unwrap() },
177 application: ApplicationDelegate{ messenger: self.inner_looper.get_messenger() },
178 application_state: self.state.clone()
179 };
180 Looper {
181 name: String::from(name),
182 port: port,
183 message_queue: VecDeque::new(),
184 handlers: handlers,
185 preferred_handler: token,
186 context: context,
187 state: initial_state,
188 terminating: false
189 }
190 }
191
192 pub fn run(mut self) -> Result<()> {
200 self.inner_looper.looper_task();
201 Ok(())
202 }
203
204 pub fn get_messenger(&self) -> Messenger {
209 self.inner_looper.get_messenger()
210 }
211}
212
213impl<A> Drop for Application<A> where A: ApplicationHooks + Send + 'static {
214 fn drop(&mut self) {
215 let (team, _) = get_current_team_and_thread();
217 let _ = ROSTER.remove_application(team);
218
219 self.link.sender.start_message(B_QUIT_REQUESTED as i32, 0).unwrap();
221 self.link.sender.flush(false).unwrap();
222 }
223}
224
225pub struct ApplicationDelegate {
227 pub messenger: Messenger
229}
230
231impl ApplicationDelegate {
232 pub fn quit(&self) {
240 let message = Message::new(QUIT);
241 self.messenger.send(message, &self.messenger).unwrap();
242 }
243}
244
245pub struct Context<A> where A: Send {
256 pub handler_messenger: Messenger,
261 pub looper: LooperDelegate,
268 pub application: ApplicationDelegate,
272 pub application_state: Arc<Mutex<A>>,
292}
293
294pub trait ApplicationHooks {
305 fn ready_to_run(&mut self, _application: &ApplicationDelegate) {
311 }
312
313 fn message_received(&mut self, _application: &ApplicationDelegate, _message: &Message) {
328 }
329
330 fn argv_received(&mut self, _application: &ApplicationDelegate, _argv: Vec<String>) {
340 }
341}
342
343struct ApplicationLooperState {}
344
345impl<A> Handler<A> for ApplicationLooperState
346 where A: ApplicationHooks + Send + 'static
347{
348 fn message_received(&mut self, context: &Context<A>, message: &Message) {
349 let mut application_state = context.application_state.lock().unwrap();
350 match message.what() {
352 B_ARGV_RECEIVED => {
353 let argv = parse_argv(message);
354 if argv.len() > 0 {
355 application_state.argv_received(&context.application, argv);
356 }
357 },
358 B_READY_TO_RUN => application_state.ready_to_run(&context.application),
359 _ => application_state.message_received(&context.application, message)
360 }
361 }
362}
363
364fn parse_argv(message: &Message) -> Vec<String> {
366 let internal = message.find_data::<bool>("_internal", 0).unwrap_or(false);
367 let mut argv: Vec<String> = Vec::new();
368 if internal {
369 for arg in args() {
371 argv.push(arg);
372 }
373 } else {
374 for i in 0.. {
375 let arg = match message.find_data::<String>("argv", i) {
376 Ok(arg) => arg,
377 Err(_) => break
378 };
379 argv.push(arg);
380 }
381 }
382 argv
383}
384
385
386pub(crate) fn get_current_team_and_thread() -> (team_id, thread_id) {
389 let mut info: thread_info = unsafe { mem::zeroed() };
390 let (team, thread) = unsafe {
391 if get_thread_info(find_thread(0 as *const i8), &mut info) == 0 {
392 (info.team, info.thread)
393 } else {
394 (-1, -1)
395 }
396 };
397 (team, thread)
398}
399
400
401#[cfg(test)]
402mod tests {
403 use super::*;
404 use app::{Message};
405 use app::sys::QUIT;
406
407 const ADD_TO_COUNTER: u32 = haiku_constant!('C','O','+','+');
408 const INFORM_APP_ABOUT_COUNTER: u32 = haiku_constant!('I','A','A','C');
409
410 struct CountLooperState {
411 count: u32
412 }
413
414 impl Handler<ApplicationState> for CountLooperState {
415 fn message_received(&mut self, context: &Context<ApplicationState>, message: &Message) {
416 match message.what() {
417 ADD_TO_COUNTER => {
418 self.count += 1;
419 let mut response = Message::new(INFORM_APP_ABOUT_COUNTER);
420 response.add_data("count", &self.count).unwrap();
421 context.application.messenger.send_and_ask_reply(response, &context.looper.messenger).unwrap();
422 },
423 _ => panic!("We are not supposed to receive messages other than ADD_TO_COUNTER"),
424 }
425 }
426 }
427
428 struct ApplicationState {
429 total_count: u32
430 }
431
432 impl ApplicationHooks for ApplicationState {
433 fn ready_to_run(&mut self, _application: &ApplicationDelegate) {
434 println!("ready_to_run()");
435 }
436
437 fn message_received(&mut self, application: &ApplicationDelegate, message: &Message) {
438 match message.what() {
439 INFORM_APP_ABOUT_COUNTER => {
440 self.total_count += 1;
441 let count = message.find_data::<u32>("count", 0).unwrap();
442 if count == 2 {
443 let messenger = message.get_return_address().unwrap();
445 messenger.send_and_ask_reply(Message::new(QUIT), &messenger).unwrap();
449 }
450 println!("total count: {}", self.total_count);
451 },
452 _ => println!("application: {}", message.what())
453 }
454
455 if self.total_count == 4 {
457 application.quit();
458 }
459 }
460 }
461
462 #[test]
463 fn looper_test() {
464 let looper_state_1 = Box::new(CountLooperState{ count: 0 });
465 let looper_state_2 = Box::new(CountLooperState{ count: 0 });
466 let application_state = ApplicationState{ total_count: 0 };
467
468 let mut application = Application::new("application/looper_test", application_state);
469
470 let looper_1 = application.create_looper("looper 1", looper_state_1);
471 let messenger_1 = looper_1.get_messenger();
472 let looper_2 = application.create_looper("looper 2", looper_state_2);
473 let messenger_2 = looper_2.get_messenger();
474 assert!(looper_1.run().is_ok());
475 assert!(looper_2.run().is_ok());
476
477 let app_messenger = application.get_messenger();
479 let message = Message::new(ADD_TO_COUNTER);
480 messenger_1.send_and_ask_reply(message, &app_messenger).unwrap();
481 let message = Message::new(ADD_TO_COUNTER);
482 messenger_2.send_and_ask_reply(message, &app_messenger).unwrap();
483 let message = Message::new(ADD_TO_COUNTER);
484 messenger_1.send_and_ask_reply(message, &app_messenger).unwrap();
485 let message = Message::new(ADD_TO_COUNTER);
486 messenger_2.send_and_ask_reply(message, &app_messenger).unwrap();
487
488 application.run().unwrap();
489 }
490}