/// Construct a new ResourceQueue system (you probably only need one) ResourceQueue* resourcequeue_new(guint structsize) { AssimObj* aself; ResourceQueue* self; BINDDEBUG(ResourceQueue); if (structsize < sizeof(ResourceQueue)) { structsize = sizeof(ResourceQueue); } aself = assimobj_new(structsize); self = NEWSUBCLASS(ResourceQueue, aself); aself->_finalize = _resource_queue_finalize; self->Qcmd = _resource_queue_Qcmd; self->cancel = _resource_queue_cancel; self->cancelall = _resource_queue_cancelall; self->resources = g_hash_table_new_full(g_str_hash, g_str_equal , _resource_queue_hash_key_destructor, _resource_queue_hash_data_destructor); self->timerid = g_timeout_add_seconds(1, _resource_queue_runqueue, self); self->activechildcnt = 0; self->shuttingdown = FALSE; return self; }
/// Discovery constructor. /// Note that derived classes <i>must</i> set the discover member function - or things might crash. /// That is certainly what will happen if you try and construct one of these objects directly and /// then use it. Discovery* discovery_new(const char * instname, ///<[in] instance name NetGSource* iosource, ///<[in/out] I/O object ConfigContext* context, ///<[in/out] configuration context gsize objsize) ///<[in] number of bytes to malloc for the object (or zero) { gsize size = objsize < sizeof(Discovery) ? sizeof(Discovery) : objsize; Discovery * ret = NEWSUBCLASS(Discovery, assimobj_new(size)); g_return_val_if_fail(ret != NULL, NULL); BINDDEBUG(Discovery); ret->_instancename = g_strdup(instname); ret->instancename = _discovery_instancename; ret->discoverintervalsecs = _discovery_discoverintervalsecs; ret->baseclass._finalize = _discovery_finalize; ret->sendjson = _discovery_sendjson; ret->discover = NULL; ret->_timerid = 0; ret->_iosource = iosource; ret->_config = context; ret->starttime = g_get_real_time(); REF(ret->_config); return ret; }
/// Construct a new CryptFrame /// This can only be used directly for creating subclassed CryptFrame frames because /// CryptFrame is an abstract class... CryptFrame* cryptframe_new( guint16 frame_type, ///<[in] TLV type of CryptFrame const char * sender_key_id, ///<[in] Sender key id const char * receiver_key_id, ///<[in] Receiver key id gsize objsize) ///<[in] size of object { Frame* baseframe; CryptFrame* self; BINDDEBUG(CryptFrame); if (objsize < sizeof(CryptFrame)) { objsize = sizeof(CryptFrame); } baseframe = frame_new(frame_type, objsize); if (!_parentclass_finalize) { _parentclass_finalize = baseframe->baseclass._finalize; } baseframe->baseclass._finalize = _cryptframe_finalize; baseframe->isvalid = _cryptframe_default_isvalid; self = NEWSUBCLASS(CryptFrame, baseframe); self->sender_key_id = g_strdup(sender_key_id); self->receiver_key_id = g_strdup(receiver_key_id); return self; }
/// Construct a new CryptCurve25519 object (frame). CryptCurve25519* cryptcurve25519_new(guint16 frame_type, ///<[in] TLV type of CryptCurve25519 const char * sender_key_id, ///<[in] name of sender's key const char * receiver_key_id, ///<[in] name of receiver's key gboolean forsending, ///<[in] TRUE if this is for sending gsize objsize) ///<[in] sizeof(this object) - or zero for default { CryptFrame* baseframe; CryptCurve25519* ret; BINDDEBUG(CryptCurve25519); if (objsize < sizeof(CryptCurve25519)) { objsize = sizeof(CryptCurve25519); } if (NULL == sender_key_id) { sender_key_id = cryptframe_get_signing_key_id(); } DEBUGMSG2("%s.%d:(%s, %s, %d)", __FUNCTION__, __LINE__, sender_key_id, receiver_key_id , (int)objsize); g_return_val_if_fail(sender_key_id != NULL && receiver_key_id != NULL, NULL); if (!_is_valid_curve25519_key_id(receiver_key_id, PUBLICKEY)) { g_critical("%s.%d: public key name [%s] is invalid", __FUNCTION__, __LINE__, receiver_key_id); return NULL; } if (!_is_valid_curve25519_key_id(sender_key_id, PUBLICKEY)) { g_critical("%s.%d: public key name [%s] is invalid", __FUNCTION__, __LINE__, sender_key_id); return NULL; } baseframe = cryptframe_new(frame_type, sender_key_id, receiver_key_id, objsize); if (!_parentclass_finalize) { _parentclass_finalize = baseframe->baseclass.baseclass._finalize; } baseframe->baseclass.isvalid = _cryptcurve25519_default_isvalid; baseframe->baseclass.updatedata = _cryptcurve25519_updatedata; baseframe->baseclass.length = TLVLEN(receiver_key_id, sender_key_id); baseframe->baseclass.baseclass._finalize = _cryptcurve25519_finalize; ret = NEWSUBCLASS(CryptCurve25519, baseframe); ret->forsending = forsending; ret->private_key = cryptframe_private_key_by_id(forsending ? sender_key_id : receiver_key_id); ret->public_key = cryptframe_public_key_by_id(forsending ? receiver_key_id : sender_key_id); if (ret->private_key && ret->public_key) { DEBUGCKSUM3("private_key:", ret->private_key->private_key, crypto_box_SECRETKEYBYTES); DEBUGCKSUM3("public_key:", ret->public_key->public_key, crypto_box_PUBLICKEYBYTES); DUMP3(__FUNCTION__, &ret->baseclass.baseclass.baseclass, " is return value"); REF(ret->private_key); REF(ret->public_key); }else{ if (!ret->private_key) { g_warning("%s.%d: Sender private key is NULL for key id %s", __FUNCTION__, __LINE__ , sender_key_id); abort(); } if (!ret->public_key) { g_warning("%s.%d: Receiver public key is NULL for key id %s", __FUNCTION__, __LINE__ , receiver_key_id); } UNREF3(ret); return NULL; } return ret; }
/** * @ref ChildProcess constructor. * Here's what we're going to do: * 1) Create child process using g_spawn_async_with_pipes() * 2) ...In child process become our own process group * 3) Create LogSourceFd object for stderr * 4) Create LogSourceFd or GMainFd object for stdout * 5) Set timer (if any) * 6) Initialize the child state to running * 7) Return. */ WINEXPORT ChildProcess* childprocess_new(gsize cpsize ///< Size of created ChildProcess object , char** argv ///< NULL-terminated argv for the ChildProcess , const char** envp ///< Environment for the ChildProcess , ConfigContext* envmod ///< Modifications to the ChildProcess environment , const char* curdir ///< Current directory to start the child in , void (*notify)(ChildProcess*, enum HowDied, int rc, int signal, gboolean core_dumped) ///< Function to call if/when the child terminates , gboolean save_stdout ///< TRUE to save stdout, FALSE to log it , const char*logdomain ///< Glib log domain , const char*logprefix ///< Prefix to prepend to log entries , GLogLevelFlags loglevel ///< Glib Log level , guint32 timeout_seconds ///< How long to wait before killing it - zero for no timeout , gpointer user_data ///< Data our user wants us to keep , enum ChildErrLogMode logmode ///< How to log child exits , const char* logname) ///< Name to use when logging child exits as requested { AssimObj* aself; ChildProcess* self; gint stdoutfd; gint stderrfd; GError* failcode = NULL; gchar** childenv = NULL; BINDDEBUG(ChildProcess); g_return_val_if_fail(logprefix != NULL, NULL); if (cpsize < sizeof(ChildProcess)) { cpsize = sizeof(ChildProcess); } aself = assimobj_new(cpsize); g_return_val_if_fail(aself != NULL, NULL); self = NEWSUBCLASS(ChildProcess, aself); childenv = assim_merge_environ(envp, envmod); if (!g_spawn_async_with_pipes( curdir, // Current directory argv, // Arguments childenv, // environment G_SPAWN_DO_NOT_REAP_CHILD, // GSpawnFlags flags, _childprocess_setup_child, // GSpawnChildSetupFunc child_setup, self, // gpointer user_data, &self->child_pid, // GPid *child_pid, NULL, // gint *standard_input, &stdoutfd, // gint *standard_output, &stderrfd, // gint *standard_error, &failcode)) { // GError **error // OOPS! Failed! const char * msg = "unknown exec error"; if (failcode && failcode->message) { msg = failcode->message; } g_critical("%s.%d: %s", __FUNCTION__, __LINE__, msg); if (failcode) { g_clear_error(&failcode); // sets failcode back to NULL } assim_free_environ(childenv); childenv = NULL; UNREF(self); aself = NULL; return NULL; } DEBUGMSG2("%s.%d: Spawned process with user_data = %p", __FUNCTION__, __LINE__, self); aself->_finalize = _childprocess_finalize; aself->toString = _childprocess_toString; self->stderr_src = logsourcefd_new(0, stderrfd, G_PRIORITY_HIGH, g_main_context_default() , logdomain, loglevel, logprefix); self->user_data = user_data; self->logmode = logmode; if (NULL == logname) { logname = argv[0]; } self->loggingname = g_strdup(logname); assim_free_environ(childenv); childenv = NULL; if (!save_stdout) { LogSourceFd* logsrc; logsrc = logsourcefd_new(0, stdoutfd, G_PRIORITY_HIGH , g_main_context_default(), logdomain, loglevel, logprefix); self->stdout_src = &logsrc->baseclass; }else{ self->stdout_src = gmainfd_new(0, stdoutfd, G_PRIORITY_HIGH, g_main_context_default()); } self->childsrc_id = g_child_watch_add(self->child_pid, _childprocess_childexit, self); self->notify = notify; if (0 == timeout_seconds) { DEBUGMSG2("No timeout for process with user_data = %p", self); self->timeoutsrc_id = 0; }else{ self->timeoutsrc_id = g_timeout_add_seconds(timeout_seconds , _childprocess_timeout, self); DEBUGMSG3("%s.%d: Set %d second timeout %d for process with user_data = %p" , __FUNCTION__, __LINE__, timeout_seconds, self->timeoutsrc_id, self); } self->child_state = CHILDSTATE_RUNNING; DEBUGMSG5("%s.%d: REF child: %p", __FUNCTION__,__LINE__, self); REF(self); // We do this because we need to still be here when the process exits return self; }
/** * Set up pcap listener for the given interfaces and protocols. * @return a properly configured pcap_t* object for listening for the given protocols - NULL on error * @see pcap_protocols */ pcap_t* create_pcap_listener(const char * dev ///<[in] Device name to listen on , gboolean blocking ///<[in] TRUE if this is a blocking connection , unsigned listenmask ///<[in] Bit mask of protocols to listen for ///< (see @ref pcap_protocols "list of valid bits") , struct bpf_program*prog) ///<[out] Compiled PCAP program { pcap_t* pcdescr = NULL; bpf_u_int32 maskp = 0; bpf_u_int32 netp = 0; char errbuf[PCAP_ERRBUF_SIZE]; char * expr = NULL; int filterlen = 1; unsigned j; int cnt=0; int rc; const char ORWORD [] = " or "; gboolean need_promisc = FALSE; BINDDEBUG(pcap_t); // setbuf(stdout, NULL); setvbuf(stdout, NULL, _IONBF, 0); errbuf[0] = '\0'; // Search the list of valid bits so we can construct the libpcap filter // for the given set of protocols on the fly... // On this pass we just compute the amount of memory we'll need... for (j = 0, cnt = 0; j < DIMOF(filterinfo); ++j) { if (listenmask & filterinfo[j].filterbit) { ++cnt; if (cnt > 1) { filterlen += sizeof(ORWORD); } filterlen += strlen(filterinfo[j].filter); } } if (filterlen < 2) { g_warning("Constructed filter is too short - invalid mask argument."); return NULL; } if (NULL == (expr = malloc(filterlen))) { g_error("Out of memory!"); return NULL; } // Same song, different verse... // This time around, we construct the filter expr[0] = '\0'; for (j = 0, cnt = 0; j < DIMOF(filterinfo); ++j) { if (listenmask & filterinfo[j].filterbit) { ++cnt; if (cnt > 1) { g_strlcat(expr, ORWORD, filterlen); } g_strlcat(expr, filterinfo[j].filter, filterlen); } } if (pcap_lookupnet(dev, &netp, &maskp, errbuf) != 0) { // This is not a problem for non-IPv4 protocols... // It just looks up the ipv4 address - which we mostly don't care about. g_info("%s.%d: pcap_lookupnet(\"%s\") failed: [%s]" , __FUNCTION__, __LINE__, dev, errbuf); } if (NULL == (pcdescr = pcap_create(dev, errbuf))) { g_warning("pcap_create failed: [%s]", errbuf); goto oopsie; } //pcap_set_promisc(pcdescr, FALSE); for (j = 0; j < DIMOF(filterinfo); ++j) { if (listenmask & filterinfo[j].filterbit) { const char * addrstring = filterinfo[j].mcastaddr; if (addrstring && !_enable_mcast_address(addrstring, dev, TRUE)) { need_promisc = TRUE; } } } pcap_set_promisc(pcdescr, need_promisc); #ifdef HAVE_PCAP_SET_RFMON pcap_set_rfmon(pcdescr, FALSE); #endif pcap_setdirection(pcdescr, PCAP_D_IN); // Weird bug - returns -3 and doesn't show an error message... // And pcap_getnonblock also returns -3... Neither should happen AFAIK... errbuf[0] = '\0'; if ((rc = pcap_setnonblock(pcdescr, !blocking, errbuf)) < 0 && errbuf[0] != '\0') { g_warning("pcap_setnonblock(%d) failed: [%s] [rc=%d]", !blocking, errbuf, rc); g_warning("Have no idea why this happens - current blocking state is: %d." , pcap_getnonblock(pcdescr, errbuf)); } pcap_set_snaplen(pcdescr, 1500); /// @todo deal with pcap_set_timeout() call here. if (blocking) { pcap_set_timeout(pcdescr, 240*1000); } else { pcap_set_timeout(pcdescr, 1); } //pcap_set_buffer_size(pcdescr, 1500); if (pcap_activate(pcdescr) != 0) { g_warning("pcap_activate failed: [%s]", pcap_geterr(pcdescr)); goto oopsie; } if (pcap_compile(pcdescr, prog, expr, FALSE, maskp) < 0) { g_warning("pcap_compile of [%s] failed: [%s]", expr, pcap_geterr(pcdescr)); goto oopsie; } if (pcap_setfilter(pcdescr, prog) < 0) { g_warning("pcap_setfilter on [%s] failed: [%s]", expr, pcap_geterr(pcdescr)); goto oopsie; } DEBUGMSG1("Compile of [%s] worked!", expr); free(expr); expr = NULL; return(pcdescr); oopsie: // Some kind of failure - free things up and return NULL g_warning("%s.%d: Could not set up PCAP on %s" , __FUNCTION__, __LINE__, dev); if (expr) { free(expr); expr = NULL; } if (pcdescr) { close_pcap_listener(pcdescr, dev, listenmask); pcdescr = NULL; } return NULL; }