1 |
|
---|
2 |
|
---|
3 | //#pragma mark - class NetworktimeprefletAsAddon -
|
---|
4 |
|
---|
5 |
|
---|
6 | class NetworktimeprefletAsAddon
|
---|
7 | {
|
---|
8 | /*
|
---|
9 | This allows to invoke the /system/preferences/Time preflet.. Not with load_image()
|
---|
10 | but outright with load_add_on() so that we can call its ntp_update_time() function directly.
|
---|
11 | The source for that particular function is here:
|
---|
12 | http://cgit.haiku-os.org/haiku/tree/src/preferences/time/ntp.cpp
|
---|
13 | which is (in the original Time preflet) called from
|
---|
14 | http://cgit.haiku-os.org/haiku/tree/src/preferences/time/NetworkTimeView.cpp
|
---|
15 | */
|
---|
16 |
|
---|
17 | public:
|
---|
18 |
|
---|
19 | NetworktimeprefletAsAddon();
|
---|
20 | ~NetworktimeprefletAsAddon();
|
---|
21 |
|
---|
22 | void UpdateSystemTime();
|
---|
23 |
|
---|
24 | private: // CODE
|
---|
25 |
|
---|
26 | static status_t thread_func( void * );
|
---|
27 |
|
---|
28 |
|
---|
29 | private: // DATA
|
---|
30 |
|
---|
31 | image_id addonId;
|
---|
32 | thread_id updaterThread;
|
---|
33 | };
|
---|
34 |
|
---|
35 |
|
---|
36 | NetworktimeprefletAsAddon::NetworktimeprefletAsAddon()
|
---|
37 | : addonId( -1 ),
|
---|
38 | updaterThread( -1 )
|
---|
39 | {
|
---|
40 | addonId = load_add_on( "/system/preferences/Time" );
|
---|
41 | if( addonId < B_OK )
|
---|
42 | {
|
---|
43 | printf( "** NetworktimeprefletAsAddon failure: can't load Time preflet: " );
|
---|
44 | perror( strerror(addonId) );
|
---|
45 | }
|
---|
46 | //printf("addonId %ld\n", addonId);
|
---|
47 | }
|
---|
48 |
|
---|
49 | NetworktimeprefletAsAddon::~NetworktimeprefletAsAddon()
|
---|
50 | {
|
---|
51 | // make sure to kill the thread dead before we unload_add_on() the add-on
|
---|
52 | // and its TEXT segment which the thread is running, or that will crash good! :
|
---|
53 |
|
---|
54 | if( updaterThread > 0 )
|
---|
55 | kill_thread( updaterThread );
|
---|
56 |
|
---|
57 | if( addonId > 0 )
|
---|
58 | unload_add_on( addonId );
|
---|
59 | }
|
---|
60 |
|
---|
61 |
|
---|
62 | void NetworktimeprefletAsAddon::UpdateSystemTime()
|
---|
63 | {
|
---|
64 | status_t (*ntp_update_time)( const char *host, const char** errorString, int32* errorCode )
|
---|
65 | = NULL
|
---|
66 | ;
|
---|
67 | status_t sta = get_image_symbol(
|
---|
68 | addonId,
|
---|
69 | "ntp_update_time__FPCcPPCcPl", // "ntp_update_time" with some gcc2 name-mangling :-/
|
---|
70 | B_SYMBOL_TYPE_TEXT,
|
---|
71 | reinterpret_cast<void**>( &ntp_update_time )
|
---|
72 | );
|
---|
73 | //printf("func %p\n", ntp_update_time);
|
---|
74 |
|
---|
75 | if( sta != B_OK || NULL == ntp_update_time )
|
---|
76 | {
|
---|
77 | printf( "** NetworktimeprefletAsAddon: get_image_symbol failure: " );
|
---|
78 | perror( strerror(sta) );
|
---|
79 |
|
---|
80 | //
|
---|
81 | return;
|
---|
82 | //
|
---|
83 | }
|
---|
84 |
|
---|
85 | updaterThread = spawn_thread(
|
---|
86 | thread_func, "(add-on)ntp_update_time",
|
---|
87 | B_NORMAL_PRIORITY,
|
---|
88 | ntp_update_time
|
---|
89 | );
|
---|
90 | resume_thread( updaterThread );
|
---|
91 |
|
---|
92 | // wait for (at most) 2 seconds:
|
---|
93 | for( int i = 0; i < 20; i++ )
|
---|
94 | {
|
---|
95 | snooze( 100000 );
|
---|
96 |
|
---|
97 | // "resume_thread" is a good way to test if a thread is still running or not:
|
---|
98 | status_t test = resume_thread( updaterThread );
|
---|
99 | //printf( "0x%lx for updaterThread\n", test );
|
---|
100 | if( B_BAD_THREAD_ID == test )
|
---|
101 | // the thread has exited, no need to wait any longer
|
---|
102 | return;
|
---|
103 | //
|
---|
104 | }
|
---|
105 |
|
---|
106 | // if we're here, we've waited for 2 seconds and the thread is STILL running...
|
---|
107 | printf( "* NetworktimeprefletAsAddon: network thread stuck for too long, aborting (will try again later)\n" );
|
---|
108 | }
|
---|
109 |
|
---|
110 | status_t NetworktimeprefletAsAddon::thread_func( void * func_inside_addon )
|
---|
111 | {
|
---|
112 | // SUMMARY
|
---|
113 | // - load settings BMessage
|
---|
114 | // - call function
|
---|
115 |
|
---|
116 | status_t (*ntp_update_time)( const char *host, const char** errorString, int32* errorCode )
|
---|
117 | = NULL
|
---|
118 | ;
|
---|
119 | (void*)ntp_update_time = func_inside_addon;
|
---|
120 |
|
---|
121 | const char * error_string = NULL;
|
---|
122 | int32 error_code = 0;
|
---|
123 | BString server;
|
---|
124 | {
|
---|
125 | // load "~/config/settings/networktime settings":
|
---|
126 | EasyMessage system_settings;
|
---|
127 | {
|
---|
128 | BPath path;
|
---|
129 | find_directory( B_USER_SETTINGS_DIRECTORY, &path );
|
---|
130 | path.Append( "networktime settings" );
|
---|
131 |
|
---|
132 | system_settings.LoadFrom( path.Path() );
|
---|
133 | }
|
---|
134 | server = system_settings.String( "server" ); // server[0] contains e.g. "pool.ntp.org"
|
---|
135 |
|
---|
136 | // notes:
|
---|
137 | // - passing "invalid.blah" results in message << NTP STATUS = 0x80006003 error_string=<Could not contact server> error_code=0x0 >>
|
---|
138 | // - passing "invalid.com" stays stuck for many seconds (the invalid.com server probably fails to respond to our port probing..)
|
---|
139 | }
|
---|
140 | ;
|
---|
141 | status_t status = ntp_update_time(
|
---|
142 | server,
|
---|
143 | &error_string,
|
---|
144 | &error_code
|
---|
145 | );
|
---|
146 |
|
---|
147 | if( B_OK != status )
|
---|
148 | printf( "** NetworktimeprefletAsAddon status = 0x%lx error_string=<%s> error_code=0x%lx\n", status, error_string, error_code );
|
---|
149 |
|
---|
150 | return 0;
|
---|
151 | }
|
---|
152 |
|
---|