int main( int argc, char* argv[]) { int result = 0; v_participantQos participantQos; u_result uresult; os_boolean success; v_subscriberQos subscriberQos; c_time resolution; c_base base; v_kernel kernel; /* Necessary to initialize the user layer. Do this just once per process.*/ mlv_init (); uresult = u_userInitialise(); mlv_setforreal (1); if(uresult == U_RESULT_OK){ /* Allocate default participant qos*/ participantQos = u_participantQosNew(NULL); { os_mutexAttr mattr; os_mutexAttrInit (&mattr); mattr.scopeAttr = OS_SCOPE_PRIVATE; os_mutexInit (&gluelock, &mattr); } if(participantQos){ if(argc > 1){ SERVICE_NAME = argv[1]; } if(argc > 2){ SERVICE_URI = argv[2]; } /*create participant*/ participant = u_participant(u_serviceNew( SERVICE_URI, 0, SERVICE_NAME, NULL, U_SERVICE_NETWORKING, (v_qos)participantQos)); if(participant){ struct cfgst *cfgst; ddsi2_participant_gid = u_entityGid (u_entity (participant)); /*Notify kernel that I am initializing. */ u_serviceChangeState(u_service(participant),STATE_INITIALISING); /*Start monitoring the splicedaemon state. I need to terminate if he says so*/ u_serviceWatchSpliceDaemon( u_service(participant), in_discoveryWatchSpliced, &terminate); if ((cfgst = config_init (participant, SERVICE_NAME)) != NULL) { unsigned rtps_flags = 0; struct nn_servicelease *servicelease; open_tracing_file (); /* Dependencies between default values is not handled automatically by the config processing (yet) */ if (config.many_sockets_mode) { if (config.max_participants == 0) config.max_participants = 100; } if (NN_STRICT_P) { /* Should not be sending invalid messages when strict */ config.respond_to_rti_init_zero_ack_with_invalid_heartbeat = 0; config.acknack_numbits_emptyset = 1; } config_print_and_free_cfgst (cfgst); servicelease = nn_servicelease_new (participant); nn_servicelease_start_renewing (servicelease); myNetworkId = getNetworkId (); u_entityAction(u_entity(participant), resolveKernelService, NULL); base = c_getBase(service); kernel = v_object(service)->kernel; rtps_init (base, kernel, config.domainId, config.participantIndex, rtps_flags, config.networkAddressString, config.peers); /* Initialize entity administration. */ success = in_entityAdminInit(participant); if(success){ /*Create subscriber to receive client writers' messages.*/ subscriberQos = u_subscriberQosNew(NULL); os_free(subscriberQos->partition); subscriberQos->partition = NULL; clientSubscriber = u_subscriberNew( participant, "clientSubscriber", subscriberQos, TRUE); if(clientSubscriber){ /*Create networkReader to be able to receive client writers' messages.*/ clientReader = u_networkReaderNew( clientSubscriber, "clientReader", NULL, TRUE); if(clientReader){ resolution.seconds = 0; resolution.nanoseconds = 10 * 1000 * 1000; /*10 ms*/ /*Create network queue*/ uresult = u_networkReaderCreateQueue( clientReader, 1000, 0, FALSE, FALSE, resolution, TRUE, &queueId, "DDSi"); if(uresult == U_RESULT_OK){ struct builtin_datareader_set drset; u_entityAction(u_entity(clientReader), resolveKernelReader, NULL); uresult = create_builtin_readers (&drset, participant); if (uresult == U_RESULT_OK) { u_serviceChangeState(u_service(participant),STATE_OPERATIONAL); uresult = attachAndMonitor(participant, &drset); if((uresult != U_RESULT_OK) && (uresult != U_RESULT_DETACHING)) { nn_log (LC_ERROR, "Abnormal termination...\n"); result = -1; } else { nn_log (LC_INFO, "Deleting entities...\n"); } destroy_builtin_readers (&drset); } else { nn_log (LC_FATAL, "Could not create subscription + readers for builtin topics.\n"); result = -1; } terminate = TRUE; v_networkReaderTrigger(vclientReader, queueId); os_threadWaitExit(clientWriterThread, NULL); } else { nn_log (LC_FATAL, "Could not create networkQueue.\n"); result = -1; } /*Clean up networkReader*/ os_mutexLock (&gluelock); u_networkReaderFree(clientReader); clientReader = NULL; vclientReader = NULL; os_mutexUnlock (&gluelock); } else { nn_log (LC_FATAL, "Could not create networkReader.\n"); result = -1; } /*Clean up subscriber*/ u_subscriberFree(clientSubscriber); } else { nn_log (LC_FATAL, "Could not create subscriber.\n"); result = -1; } /*Clean up entity administration*/ in_entityAdminDestroy(); } else { nn_log (LC_FATAL, "Could not initialize entity adminstration.\n"); result = -1; } /* RTPS layer now defines types, cleanup before detaching */ rtps_term(); /*Notify kernel that I've terminated*/ u_serviceChangeState(u_service(participant),STATE_TERMINATED); nn_servicelease_free (servicelease); /*Delete participant*/ uresult = u_serviceFree(u_service(participant)); if(uresult != U_RESULT_OK){ nn_log (LC_FATAL, "Deletion of participant failed.\n"); result = -1; } } else { nn_log (LC_FATAL, "Initialization of configuration failed.\n"); result = -1; } } else { nn_log (LC_FATAL, "Could not create participant.\n"); result = -1; } u_participantQosFree (participantQos); } else { nn_log (LC_FATAL, "Could not allocate participantQos.\n"); result = -1; } os_mutexDestroy (&gluelock); /* Detach user layer */ mlv_setforreal (0); uresult = u_userDetach(); mlv_fini (); if(uresult != U_RESULT_OK){ nn_log (LC_FATAL, "Detachment of user layer failed.\n"); result = -1; } } else { nn_log (LC_FATAL, "Initialization of user layer failed.\n"); result = -1; } nn_log (LC_INFO, "Finis.\n"); /* Must be really late, or nn_log becomes unhappy -- but it should be before os_osExit (which appears to be called from u_userExit(), which is not called by u_userDetach but by an exit handler, it appears.) */ config_fini (); return result; }
nw_channelWriter nw_channelWriterNew( const char *serviceName, const char *pathName, nw_sendChannel sendChannel, u_networkReader reader, c_ulong stat_channel_id) { nw_channelWriter result = NULL; c_ulong queueSize; c_ulong priority; c_bool reliable; c_bool useAsDefault; static c_bool defaultDefined = FALSE; u_result ures; c_ulong resolutionMsecs; c_time resolution; char *tmpPath; size_t tmpPathSize; char* name; result = (nw_channelWriter)os_malloc((os_uint32)sizeof(*result)); if (result != NULL) { /* Initialize parent */ /* First determine its parameter path */ tmpPathSize = strlen(pathName) + strlen(NWCF_SEP) + strlen(NWCF_ROOT(Tx)) + strlen(NWCF_SEP) + strlen(NWCF_ROOT(Scheduling)) + 1 /* '\0' */; tmpPath = os_malloc(tmpPathSize); os_sprintf(tmpPath, "%s%s%s%s%s", pathName, NWCF_SEP, NWCF_ROOT(Tx), NWCF_SEP, NWCF_ROOT(Scheduling)); nw_channelUserInitialize((nw_channelUser)result, pathName /* use pathName as name */, tmpPath, reader, nw_channelWriterMainFunc, nw_channelWriterTrigger, nw_channelWriterFinalize); os_free(tmpPath); /* Own initialization */ result->serviceName = os_strdup(serviceName); /* Store the channel to write to */ result->sendChannel = sendChannel; /* Create a new networking queue */ /* First read the corresponding options */ queueSize = NWCF_SIMPLE_SUBPARAM(ULong, pathName, Tx, QueueSize); priority = NWCF_SIMPLE_ATTRIB(ULong, pathName, priority); reliable = NWCF_SIMPLE_ATTRIB(Bool, pathName, reliable); useAsDefault = NWCF_SIMPLE_ATTRIB(Bool, pathName, default); name = NWCF_DEFAULTED_ATTRIB(String, pathName, ChannelName,"unnamed","unnamed"); if (useAsDefault) { if (defaultDefined) { NW_REPORT_WARNING_1( "initializing network", "default channel redefined by channel \"%s\"", pathName); useAsDefault = FALSE; } else { defaultDefined = TRUE; } } result->scs = nw_SendChannelStatisticsNew(); result->stat_channel_id = stat_channel_id; resolutionMsecs = NWCF_SIMPLE_PARAM(ULong, pathName, Resolution); if (resolutionMsecs < NWCF_MIN(Resolution)) { NW_REPORT_WARNING_3( "initializing network", "Requested value %d for resolution period for channel \"%s\" is " "too small, using %d instead", resolutionMsecs, pathName, NWCF_MIN(Resolution)); resolutionMsecs = NWCF_MIN(Resolution); } resolution.seconds = resolutionMsecs/1000; resolution.nanoseconds = 1000000*(resolutionMsecs % 1000); tmpPathSize = strlen(pathName) + strlen(NWCF_SEP) + strlen(NWCF_ROOT(Tx)) + 1; tmpPath = os_malloc(tmpPathSize); os_sprintf(tmpPath, "%s%s%s", pathName, NWCF_SEP, NWCF_ROOT(Tx)); result->reportInterval = NWCF_SIMPLE_PARAM(ULong, tmpPath, ReportInterval); if (result->reportInterval < NWCF_MIN(ReportInterval)) { NW_REPORT_WARNING_3( "initializing network", "Requested report interval value %d for channel \"%s\" is " "too small, using %d instead", result->reportInterval, pathName, NWCF_MIN(ReportInterval)); result->reportInterval = NWCF_MIN(ReportInterval); } os_free(tmpPath); ures = u_networkReaderCreateQueue(reader, queueSize, priority, reliable, FALSE, resolution, useAsDefault, &result->queueId, name); os_free(name); if (ures != U_RESULT_OK) { NW_REPORT_ERROR_1( "initializing network", "creation of network queue failed for channel \"%s\"", pathName); } }