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
11 #include "osrf_router.h"
12 #include <opensrf/osrfConfig.h>
13 #include <opensrf/utils.h>
14 #include <opensrf/log.h>
15 #include <opensrf/osrf_json.h>
19 An osrfRouter contains various bits and scraps that the router uses for networking.
21 static osrfRouter* router = NULL;
24 @brief Respond to signal by exiting immediately.
25 @param signo The signal number.
27 void routerSignalHandler( int signo ) {
28 osrfLogWarning( OSRF_LOG_MARK, "Received signal [%d], cleaning up...", signo );
30 /* for now, just forcibly exit. This is not a friendly way to clean up, but
31 * there is a bug in osrfRouterFree() (in particular with cleaning up sockets),
32 * that can cause the router process to stick around. If we do this, we
33 * are guaranteed to exit.
38 osrfRouterFree(router);
41 // Exit by re-raising the signal so that the parent
42 // process can detect it
44 signal( signo, SIG_DFL );
48 static void setupRouter(jsonObject* configChunk);
52 @brief The top-level function of the router program.
53 @param argc Number of items in command line.
54 @param argv Pointer to array of items on command line.
55 @return System return code.
57 Load configuration file, spawn one or more child processes, and exit.
59 int main( int argc, char* argv[] ) {
62 osrfLogError( OSRF_LOG_MARK,
63 "Usage: %s <path_to_config_file> <config_context>", argv[0] );
67 const char* config_file = argv[1];
68 const char* context = argv[2];
70 /* Get a set of router definitions from a config file */
72 osrfConfig* cfg = osrfConfigInit(config_file, context);
74 osrfLogError( OSRF_LOG_MARK, "Router can't load config file %s", config_file );
78 osrfConfigSetDefaultConfig(cfg);
79 jsonObject* configInfo = osrfConfigGetValueObject(NULL, "/router");
81 if( configInfo->size < 1 || NULL == jsonObjectGetIndex( configInfo, 1 ) ) {
82 osrfLogError( OSRF_LOG_MARK, "No routers defined in config file %s, context \"%s\"",
83 config_file, context );
87 /* We're done with the command line now, */
88 /* so we can safely overlay it */
90 init_proc_title( argc, argv );
91 set_proc_title( "OpenSRF Router" );
93 /* Spawn child process(es) */
96 for(i = 0; i < configInfo->size; i++) {
97 jsonObject* configChunk = jsonObjectGetIndex(configInfo, i);
98 if(fork() == 0) { /* create a new child to run this router instance */
99 setupRouter(configChunk);
100 break; /* We're a child; don't spawn any more children here */
108 @brief Configure and run a child process.
109 @param configChunk Pointer to a subset of the loaded configuration.
111 Configure oneself, daemonize, and then call osrfRouterRun() to go into an infinite
112 loop. Do not return unless something goes wrong.
114 static void setupRouter(jsonObject* configChunk) {
116 jsonObject* transport_cfg = jsonObjectGetKey( configChunk, "transport" );
117 if( ! transport_cfg ) {
118 //fprintf( stderr, "Child router process %ld has no transport configuration\n", (long) getpid() );
119 return; /* these are not the configs you're looking for */
122 const char* server = jsonObjectGetString( jsonObjectGetKey( transport_cfg, "server" ) );
123 const char* port = jsonObjectGetString( jsonObjectGetKey( transport_cfg, "port" ) );
124 const char* username = jsonObjectGetString( jsonObjectGetKey( transport_cfg, "username" ) );
125 const char* password = jsonObjectGetString( jsonObjectGetKey( transport_cfg, "password" ) );
126 const char* resource = jsonObjectGetString( jsonObjectGetKey( transport_cfg, "resource" ) );
128 const char* level = jsonObjectGetString( jsonObjectGetKey( configChunk, "loglevel" ) );
129 const char* log_file = jsonObjectGetString( jsonObjectGetKey( configChunk, "logfile" ) );
130 const char* facility = jsonObjectGetString( jsonObjectGetKey( configChunk, "syslog" ) );
133 if(level) llevel = atoi(level);
137 fprintf(stderr, "Log file name not specified for router\n");
141 if(!strcmp(log_file, "syslog")) {
142 osrfLogInit( OSRF_LOG_TYPE_SYSLOG, "router", llevel );
143 osrfLogSetSyslogFacility(osrfLogFacilityToInt(facility));
146 osrfLogInit( OSRF_LOG_TYPE_FILE, "router", llevel );
147 osrfLogSetFile( log_file );
150 osrfLogInfo( OSRF_LOG_MARK, "Router connecting as: server: %s port: %s "
151 "user: %s resource: %s", server, port, username, resource );
154 if(port) iport = atoi( port );
156 osrfStringArray* tclients = osrfNewStringArray(4);
157 osrfStringArray* tservers = osrfNewStringArray(4);
159 jsonObject* tclientsList = jsonObjectFindPath(configChunk, "/trusted_domains/client");
160 jsonObject* tserversList = jsonObjectFindPath(configChunk, "/trusted_domains/server");
164 if(tserversList->type == JSON_ARRAY) {
165 for( i = 0; i != tserversList->size; i++ ) {
166 const char* serverDomain = jsonObjectGetString(jsonObjectGetIndex(tserversList, i));
167 osrfLogInfo( OSRF_LOG_MARK, "Router adding trusted server: %s", serverDomain);
168 osrfStringArrayAdd(tservers, serverDomain);
171 const char* serverDomain = jsonObjectGetString(tserversList);
172 osrfLogInfo( OSRF_LOG_MARK, "Router adding trusted server: %s", serverDomain);
173 osrfStringArrayAdd(tservers, serverDomain);
176 if(tclientsList->type == JSON_ARRAY) {
177 for( i = 0; i != tclientsList->size; i++ ) {
178 const char* clientDomain = jsonObjectGetString(jsonObjectGetIndex(tclientsList, i));
179 osrfLogInfo( OSRF_LOG_MARK, "Router adding trusted client: %s", clientDomain);
180 osrfStringArrayAdd(tclients, clientDomain);
183 const char* clientDomain = jsonObjectGetString(tclientsList);
184 osrfLogInfo( OSRF_LOG_MARK, "Router adding trusted client: %s", clientDomain);
185 osrfStringArrayAdd(tclients, clientDomain);
189 if( tclients->size == 0 || tservers->size == 0 ) {
190 osrfLogError( OSRF_LOG_MARK, "We need trusted servers and trusted client to run the router...");
191 osrfStringArrayFree( tservers );
192 osrfStringArrayFree( tclients );
196 router = osrfNewRouter( server,
197 username, resource, password, iport, tclients, tservers );
199 signal(SIGHUP,routerSignalHandler);
200 signal(SIGINT,routerSignalHandler);
201 signal(SIGTERM,routerSignalHandler);
203 if( (osrfRouterConnect(router)) != 0 ) {
204 fprintf(stderr, "Unable to connect router to jabber server %s... exiting\n", server );
205 osrfRouterFree(router);
210 osrfRouterRun( router );
212 // Shouldn't get here, since osrfRouterRun()
213 // should go into an infinite loop
215 osrfRouterFree(router);