.TH "globus_net_manager_tutorial" 3 "Fri Nov 11 2016" "Version 0.16" "globus_net_manager" \" -*- nroff -*- .ad l .nh .SH NAME globus_net_manager_tutorial \- Net Manager Implementation Tutorial This example uses functionality from globus_common and globus_net_manager modules, so the headers for those must be included: .PP .nf #include "globus_common.h" #include "globus_net_manager.h" .fi .PP To implement a network manager, define a struct \fBglobus_net_manager_s\fP containing pointers to the functions in your code that you want invoked during network events, and pass that to \fBglobus_net_manager_register()\fP\&. Applications which use the \fBContext\fP functions or the \fBGlobus XIO Net Manager Driver\fP will invoke your functions as network operations occur\&. For this example (and I would imagine most real implementations), the globus_net_manager_t is statically initialized, like this: .PP .PP .nf static globus_net_manager_t globus_l_net_manager_logging = { "logging", globus_l_net_manager_logging_pre_listen, globus_l_net_manager_logging_post_listen, globus_l_net_manager_logging_end_listen, globus_l_net_manager_logging_pre_accept, globus_l_net_manager_logging_post_accept, globus_l_net_manager_logging_pre_connect, globus_l_net_manager_logging_post_connect, globus_l_net_manager_logging_pre_close, globus_l_net_manager_logging_post_close }; .fi .PP For the examples provided in this library, the \fBglobus_net_manager_s\fP is registered during module activation in a globus_extension module\&. This method makes it easy to use network managers in a shared library environment\&. This is also a good place to initialize any state that you need to retain between calls to the network manager\&. .PP To implement this, do the following: .PP .nf static int globus_l_net_manager_logging_activate(void) { globus_hashtable_init( &globus_l_nm_logging_logfiles, 7, globus_hashtable_string_hash, globus_hashtable_string_keyeq); int rc = globus_module_activate(GLOBUS_NET_MANAGER_MODULE); if (rc == 0) { rc = globus_net_manager_register( &globus_l_net_manager_logging, GlobusExtensionMyModule(globus_net_manager_logging)); } return rc; } static void globus_l_logging_logfiles_destroy(void *datum) { globus_l_nm_logging_logref_t *logref = datum; if (logref) { free(logref->key); fclose(logref->handle); free(logref); } } static int globus_l_net_manager_logging_deactivate(void) { globus_hashtable_destroy_all( &globus_l_nm_logging_logfiles, globus_l_logging_logfiles_destroy); int rc = globus_net_manager_unregister(&globus_l_net_manager_logging); if (rc == 0) { rc = globus_module_deactivate(GLOBUS_NET_MANAGER_MODULE); } return rc; } .fi .PP .PP Finally, the real work of the manager is done in the functions registered in the \fBglobus_net_manager_s\fP\&. For brevity, I'll just include the pre_listen function in this tutorial\&. This function is passed the task-id associated with the operation, the transport ('tcp', 'udp', 'udt', etc) used by the network, and whatever attributes are associated with the operation\&. If we wanted to modify things before they were processed by the network, we could create a modified copy of the attributes in the pre_listen function and return them via the attr_array_out parameter\&. In this case, we simply print out the information we've received from the network stack\&. .PP .PP .nf static globus_result_t globus_l_net_manager_logging_pre_listen( struct globus_net_manager_s *manager, const globus_net_manager_attr_t *manager_attr_array, const char *task_id, const char *transport, const globus_net_manager_attr_t *attr_array, globus_net_manager_attr_t **attr_array_out) { FILE * logfile; logfile = globus_l_net_manager_logging_get_logfile(manager_attr_array); globus_l_net_manager_logging_log_header(logfile, manager, task_id, transport, "pre_listen"); globus_l_net_manager_logging_log_attrs(logfile, attr_array); globus_l_net_manager_logging_log_footer(logfile); return GLOBUS_SUCCESS; } /* globus_l_net_manager_logging_pre_listen() */ .fi .PP