2 @file osrf_router_main.c
3 @brief top level of OSRF Router
5 This top level loads a configuration file and forks into one or more child
6 processes. Each child process configures itself, daemonizes itself, and then (via a
7 call to osrfRouterRun()) goes into an infinite loop to route messages among clients
10 The first command-line parameter is the name of the configuration file.
12 The second command-line parameter is the context -- an XML tag identifying the subset
13 of the configuration file that is relevant to this application (since a configuration
14 file may include information for multiple applications).
16 Any subsequent command-line parameters are silently ignored.
19 #include "osrf_router.h"
20 #include <opensrf/osrfConfig.h>
21 #include <opensrf/utils.h>
22 #include <opensrf/log.h>
23 #include <opensrf/osrf_json.h>
27 An osrfRouter contains various bits and scraps that the router uses for networking.
29 static osrfRouter* router = NULL;
32 @brief Respond to signal by exiting immediately.
33 @param signo The signal number.
35 void routerSignalHandler( int signo ) {
36 osrfLogWarning( OSRF_LOG_MARK, "Received signal [%d], cleaning up...", signo );
38 /* for now, just forcibly exit. This is not a friendly way to clean up, but
39 * there is a bug in osrfRouterFree() (in particular with cleaning up sockets),
40 * that can cause the router process to stick around. If we do this, we
41 * are guaranteed to exit.
46 osrfRouterFree(router);
49 // Exit by re-raising the signal so that the parent
50 // process can detect it
52 signal( signo, SIG_DFL );
56 static void setupRouter(jsonObject* configChunk);
60 @brief The top-level function of the router program.
61 @param argc Number of items in command line.
62 @param argv Pointer to array of items on command line.
63 @return System return code.
65 Load configuration file, spawn zero or more child processes, and exit.
67 int main( int argc, char* argv[] ) {
70 osrfLogError( OSRF_LOG_MARK,
71 "Usage: %s <path_to_config_file> <config_context>", argv[0] );
75 const char* config_file = argv[1];
76 const char* context = argv[2];
78 /* Get a set of router definitions from a config file */
80 osrfConfig* cfg = osrfConfigInit(config_file, context);
82 osrfLogError( OSRF_LOG_MARK, "Router can't load config file %s", config_file );
86 osrfConfigSetDefaultConfig(cfg);
87 jsonObject* configInfo = osrfConfigGetValueObject(NULL, "/router");
89 if( configInfo->size < 1 || NULL == jsonObjectGetIndex( configInfo, 1 ) ) {
90 osrfLogError( OSRF_LOG_MARK, "No routers defined in config file %s, context \"%s\"",
91 config_file, context );
95 /* We're done with the command line now, */
96 /* so we can safely overlay it */
98 init_proc_title( argc, argv );
99 set_proc_title( "OpenSRF Router" );
101 /* Spawn child process(es) */
104 for(i = 0; i < configInfo->size; i++) {
105 jsonObject* configChunk = jsonObjectGetIndex(configInfo, i);
106 if( ! jsonObjectGetKey( configChunk, "transport" ) )
108 // In searching the configuration file for a given context, we may have found a spurious
109 // hit on an unrelated part of the configuration file that happened to use the same XML
110 // tag. In fact this happens routinely in practice.
112 // If we don't see a member for "transport" then this is presumably such a spurious hit,
113 // so we silently ignore it.
115 // It is also possible that it's the right part of the configuration file but it has a
116 // typo or other such error, making it look spurious. In that case, well, too bad.
119 if(fork() == 0) { /* create a new child to run this router instance */
120 setupRouter(configChunk);
121 break; /* We're a child; don't spawn any more children here */
129 @brief Configure and run a child process.
130 @param configChunk Pointer to a subset of the loaded configuration.
132 Configure oneself, daemonize, and then call osrfRouterRun() to go into an infinite
133 loop. Do not return unless something goes wrong.
135 static void setupRouter(jsonObject* configChunk) {
137 jsonObject* transport_cfg = jsonObjectGetKey( configChunk, "transport" );
139 const char* server = jsonObjectGetString( jsonObjectGetKey( transport_cfg, "server" ) );
140 const char* port = jsonObjectGetString( jsonObjectGetKey( transport_cfg, "port" ) );
141 const char* username = jsonObjectGetString( jsonObjectGetKey( transport_cfg, "username" ) );
142 const char* password = jsonObjectGetString( jsonObjectGetKey( transport_cfg, "password" ) );
143 const char* resource = jsonObjectGetString( jsonObjectGetKey( transport_cfg, "resource" ) );
145 const char* level = jsonObjectGetString( jsonObjectGetKey( configChunk, "loglevel" ) );
146 const char* log_file = jsonObjectGetString( jsonObjectGetKey( configChunk, "logfile" ) );
147 const char* facility = jsonObjectGetString( jsonObjectGetKey( configChunk, "syslog" ) );
150 if(level) llevel = atoi(level);
154 fprintf(stderr, "Log file name not specified for router\n");
158 if(!strcmp(log_file, "syslog")) {
159 osrfLogInit( OSRF_LOG_TYPE_SYSLOG, "router", llevel );
160 osrfLogSetSyslogFacility(osrfLogFacilityToInt(facility));
163 osrfLogInit( OSRF_LOG_TYPE_FILE, "router", llevel );
164 osrfLogSetFile( log_file );
167 osrfLogInfo( OSRF_LOG_MARK, "Router connecting as: server: %s port: %s "
168 "user: %s resource: %s", server, port, username, resource );
171 if(port) iport = atoi( port );
173 osrfStringArray* tclients = osrfNewStringArray(4);
174 osrfStringArray* tservers = osrfNewStringArray(4);
176 jsonObject* tclientsList = jsonObjectFindPath(configChunk, "/trusted_domains/client");
177 jsonObject* tserversList = jsonObjectFindPath(configChunk, "/trusted_domains/server");
181 if(tserversList->type == JSON_ARRAY) {
182 for( i = 0; i != tserversList->size; i++ ) {
183 const char* serverDomain = jsonObjectGetString(jsonObjectGetIndex(tserversList, i));
184 osrfLogInfo( OSRF_LOG_MARK, "Router adding trusted server: %s", serverDomain);
185 osrfStringArrayAdd(tservers, serverDomain);
188 const char* serverDomain = jsonObjectGetString(tserversList);
189 osrfLogInfo( OSRF_LOG_MARK, "Router adding trusted server: %s", serverDomain);
190 osrfStringArrayAdd(tservers, serverDomain);
193 if(tclientsList->type == JSON_ARRAY) {
194 for( i = 0; i != tclientsList->size; i++ ) {
195 const char* clientDomain = jsonObjectGetString(jsonObjectGetIndex(tclientsList, i));
196 osrfLogInfo( OSRF_LOG_MARK, "Router adding trusted client: %s", clientDomain);
197 osrfStringArrayAdd(tclients, clientDomain);
200 const char* clientDomain = jsonObjectGetString(tclientsList);
201 osrfLogInfo( OSRF_LOG_MARK, "Router adding trusted client: %s", clientDomain);
202 osrfStringArrayAdd(tclients, clientDomain);
206 if( tclients->size == 0 || tservers->size == 0 ) {
207 osrfLogError( OSRF_LOG_MARK, "We need trusted servers and trusted client to run the router...");
208 osrfStringArrayFree( tservers );
209 osrfStringArrayFree( tclients );
213 router = osrfNewRouter( server,
214 username, resource, password, iport, tclients, tservers );
216 signal(SIGHUP,routerSignalHandler);
217 signal(SIGINT,routerSignalHandler);
218 signal(SIGTERM,routerSignalHandler);
220 if( (osrfRouterConnect(router)) != 0 ) {
221 fprintf(stderr, "Unable to connect router to jabber server %s... exiting\n", server );
222 osrfRouterFree(router);
227 osrfRouterRun( router );
229 // Shouldn't get here, since osrfRouterRun()
230 // should go into an infinite loop
232 osrfRouterFree(router);