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 cleaning up and exiting immediately.
33 @param signo The signal number.
35 void routerSignalHandler( int signo ) {
36 osrfLogWarning( OSRF_LOG_MARK, "Received signal [%d], cleaning up...", signo );
39 osrfRouterFree(router);
40 osrfLogWarning( OSRF_LOG_MARK, "Cleanup successful. Re-raising signal" );
43 // Re-raise the signal so that the parent process can detect it.
45 signal( signo, SIG_DFL );
49 static void setupRouter(jsonObject* configChunk);
53 @brief The top-level function of the router program.
54 @param argc Number of items in command line.
55 @param argv Pointer to array of items on command line.
56 @return System return code.
58 Load configuration file, spawn zero or more child processes, and exit.
60 int main( int argc, char* argv[] ) {
63 osrfLogError( OSRF_LOG_MARK,
64 "Usage: %s <path_to_config_file> <config_context>", argv[0] );
68 const char* config_file = argv[1];
69 const char* context = argv[2];
71 /* Get a set of router definitions from a config file */
73 osrfConfig* cfg = osrfConfigInit(config_file, context);
75 osrfLogError( OSRF_LOG_MARK, "Router can't load config file %s", config_file );
79 osrfConfigSetDefaultConfig(cfg);
80 jsonObject* configInfo = osrfConfigGetValueObject(NULL, "/router");
82 if( configInfo->size < 1 || NULL == jsonObjectGetIndex( configInfo, 1 ) ) {
83 osrfLogError( OSRF_LOG_MARK, "No routers defined in config file %s, context \"%s\"",
84 config_file, context );
88 /* We're done with the command line now, */
89 /* so we can safely overlay it */
91 init_proc_title( argc, argv );
92 set_proc_title( "OpenSRF Router" );
94 /* Spawn child process(es) */
97 for(i = 0; i < configInfo->size; i++) {
98 jsonObject* configChunk = jsonObjectGetIndex(configInfo, i);
99 if( ! jsonObjectGetKey( configChunk, "transport" ) )
101 // In searching the configuration file for a given context, we may have found a spurious
102 // hit on an unrelated part of the configuration file that happened to use the same XML
103 // tag. In fact this happens routinely in practice.
105 // If we don't see a member for "transport" then this is presumably such a spurious hit,
106 // so we silently ignore it.
108 // It is also possible that it's the right part of the configuration file but it has a
109 // typo or other such error, making it look spurious. In that case, well, too bad.
112 if(fork() == 0) { /* create a new child to run this router instance */
113 setupRouter(configChunk);
114 break; /* We're a child; don't spawn any more children here */
122 @brief Configure and run a child process.
123 @param configChunk Pointer to a subset of the loaded configuration.
125 Configure oneself, daemonize, and then call osrfRouterRun() to go into an infinite
126 loop. Do not return unless something goes wrong.
128 static void setupRouter(jsonObject* configChunk) {
130 jsonObject* transport_cfg = jsonObjectGetKey( configChunk, "transport" );
132 const char* server = jsonObjectGetString( jsonObjectGetKey( transport_cfg, "server" ) );
133 const char* port = jsonObjectGetString( jsonObjectGetKey( transport_cfg, "port" ) );
134 const char* username = jsonObjectGetString( jsonObjectGetKey( transport_cfg, "username" ) );
135 const char* password = jsonObjectGetString( jsonObjectGetKey( transport_cfg, "password" ) );
136 const char* resource = jsonObjectGetString( jsonObjectGetKey( transport_cfg, "resource" ) );
138 const char* level = jsonObjectGetString( jsonObjectGetKey( configChunk, "loglevel" ) );
139 const char* log_file = jsonObjectGetString( jsonObjectGetKey( configChunk, "logfile" ) );
140 const char* facility = jsonObjectGetString( jsonObjectGetKey( configChunk, "syslog" ) );
143 if(level) llevel = atoi(level);
147 fprintf(stderr, "Log file name not specified for router\n");
151 if(!strcmp(log_file, "syslog")) {
152 osrfLogInit( OSRF_LOG_TYPE_SYSLOG, "router", llevel );
153 osrfLogSetSyslogFacility(osrfLogFacilityToInt(facility));
156 osrfLogInit( OSRF_LOG_TYPE_FILE, "router", llevel );
157 osrfLogSetFile( log_file );
160 osrfLogInfo( OSRF_LOG_MARK, "Router connecting as: server: %s port: %s "
161 "user: %s resource: %s", server, port, username, resource );
164 if(port) iport = atoi( port );
166 osrfStringArray* tclients = osrfNewStringArray(4);
167 osrfStringArray* tservers = osrfNewStringArray(4);
169 jsonObject* tclientsList = jsonObjectFindPath(configChunk, "/trusted_domains/client");
170 jsonObject* tserversList = jsonObjectFindPath(configChunk, "/trusted_domains/server");
174 if(tserversList->type == JSON_ARRAY) {
175 for( i = 0; i != tserversList->size; i++ ) {
176 const char* serverDomain = jsonObjectGetString(jsonObjectGetIndex(tserversList, i));
177 osrfLogInfo( OSRF_LOG_MARK, "Router adding trusted server: %s", serverDomain);
178 osrfStringArrayAdd(tservers, serverDomain);
181 const char* serverDomain = jsonObjectGetString(tserversList);
182 osrfLogInfo( OSRF_LOG_MARK, "Router adding trusted server: %s", serverDomain);
183 osrfStringArrayAdd(tservers, serverDomain);
186 if(tclientsList->type == JSON_ARRAY) {
187 for( i = 0; i != tclientsList->size; i++ ) {
188 const char* clientDomain = jsonObjectGetString(jsonObjectGetIndex(tclientsList, i));
189 osrfLogInfo( OSRF_LOG_MARK, "Router adding trusted client: %s", clientDomain);
190 osrfStringArrayAdd(tclients, clientDomain);
193 const char* clientDomain = jsonObjectGetString(tclientsList);
194 osrfLogInfo( OSRF_LOG_MARK, "Router adding trusted client: %s", clientDomain);
195 osrfStringArrayAdd(tclients, clientDomain);
199 if( tclients->size == 0 || tservers->size == 0 ) {
200 osrfLogError( OSRF_LOG_MARK, "We need trusted servers and trusted client to run the router...");
201 osrfStringArrayFree( tservers );
202 osrfStringArrayFree( tclients );
206 router = osrfNewRouter( server,
207 username, resource, password, iport, tclients, tservers );
209 signal(SIGHUP,routerSignalHandler);
210 signal(SIGINT,routerSignalHandler);
211 signal(SIGTERM,routerSignalHandler);
213 if( (osrfRouterConnect(router)) != 0 ) {
214 fprintf(stderr, "Unable to connect router to jabber server %s... exiting\n", server );
215 osrfRouterFree(router);
220 osrfRouterRun( router );
222 // Shouldn't get here, since osrfRouterRun()
223 // should go into an infinite loop
225 osrfRouterFree(router);