static gboolean glib_main (gpointer data) { xmlDoc *doc = NULL; xmlNode *root_element = NULL; struct connection conn; static struct start_network_data start_network_data; if (!(start_network_data.client = nm_client_new())) { network_status (NULL, "Unable to connect to NetworkManager"); g_main_loop_quit (loop); return FALSE; } g_timeout_add_seconds (2, do_timeout, &start_network_data); start_network_data.should_quit = TRUE; /*parse the file and get the DOM */ if( NULL == (doc = xmlReadFile(NETWORK_CONFIG, NULL, 0))) { network_status (start_network_data.client, "error: Could not parse " NETWORK_CONFIG "\n"); g_main_loop_quit (loop); return FALSE; } /*Get the root element node */ root_element = xmlDocGetRootElement(doc); if (root_element->type == XML_ELEMENT_NODE && !strcmp((char *)root_element->name, "configuration")) { gchar *err = read_connection(&conn, root_element); if (err) { gchar err2[1024]; g_snprintf(err2, sizeof(err2), "Unable to parse configuration data: %s", err); network_status (start_network_data.client, err2); g_main_loop_quit (loop); return FALSE; } } else { network_status (start_network_data.client, "error: Invalid " NETWORK_CONFIG " file: No <configuration/> root node\n"); g_main_loop_quit (loop); return FALSE; } xmlFreeDoc(doc); xmlCleanupParser(); /* Generate the UUID from the connection information */ generate_uuid(&conn, start_network_data.uuid, sizeof(start_network_data.uuid)); /* Hand control over to do_connection. Execution will continue in callbacks. */ do_connection(&start_network_data); return FALSE; }
void main_loop(){ do { network_status(); sleep(300); } while(1); }
static void connections_read (NMSettingsInterface *settings, gpointer user_data) { GSList *connections; NMConnection *connection; NMDevice *dev; struct start_network_data *data = (struct start_network_data *)user_data; static int tries = 0; if(!NM_IS_REMOTE_SETTINGS_SYSTEM(settings)) { network_status (data->client, "Not a settings_system object! Huh?\n"); g_main_loop_quit (loop); return; } connections = nm_settings_interface_list_connections (settings); connection = find_connection(connections, data->uuid); if (!connection) { if (tries++ >= 2) { network_status (data->client, "Unable to find connection from " NETWORK_CONFIG " in system configs file"); g_main_loop_quit(loop); return; } return; } dev = get_device_for_connection (data->client, connection); if (!dev) { network_status (data->client, "Unable to find correct device for connection"); g_main_loop_quit(loop); return; } data->should_quit = FALSE; nm_client_activate_connection (data->client, NM_DBUS_SERVICE_SYSTEM_SETTINGS, nm_connection_get_path (connection),//con_path, dev,//device, NULL,//spec_object, activate_connection_cb, data); return; }
static void active_connection_state_cb (NMActiveConnection *active, GParamSpec *pspec, gpointer user_data) { NMActiveConnectionState state; struct start_network_data *data = (struct start_network_data *)user_data; state = nm_active_connection_get_state (active); if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) { /* Successful connection */ network_status (data->client, NULL); g_main_loop_quit (loop); return; } else if (state == NM_ACTIVE_CONNECTION_STATE_UNKNOWN) { network_status (data->client, "Connection activation failed.\n"); g_main_loop_quit (loop); return; } }
static gboolean do_timeout (gpointer user_data) { struct start_network_data *data = (struct start_network_data *)user_data; if (data->should_quit) { network_status (data->client, "error: Connect timed out\n"); g_main_loop_quit (loop); return FALSE; } return TRUE; }
static void do_connection (struct start_network_data *user_data) { DBusGConnection *bus; GError *error = NULL; NMRemoteSettingsSystem *system_settings; gboolean system_settings_running; struct start_network_data *data = (struct start_network_data *)user_data; bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); if (!bus || error) { network_status (data->client, "Unable to connect to system bus"); g_main_loop_quit (loop); goto out; } system_settings = nm_remote_settings_system_new(bus); if(!system_settings) { network_status (data->client, "Unable to get system settings"); g_main_loop_quit (loop); goto out; } g_object_get (system_settings, NM_REMOTE_SETTINGS_SERVICE_RUNNING, &system_settings_running, NULL); if(!system_settings_running) { network_status (data->client, "System settings service is not running"); g_main_loop_quit (loop); goto out; } g_signal_connect (system_settings, NM_SETTINGS_INTERFACE_CONNECTIONS_READ, G_CALLBACK (connections_read), data); out: if (bus) dbus_g_connection_unref(bus); return; }
static void activate_connection_cb (gpointer user_data, const char *path, GError *error) { struct start_network_data *data = (struct start_network_data *)user_data; NMActiveConnection *active; NMActiveConnectionState state; if (error) { gchar err[512]; g_snprintf (err, sizeof(err), "Unable to connect: %s", error->message); network_status (data->client, err); g_main_loop_quit (loop); return; } active = nm_client_get_active_connection_by_path (data->client, path); if (!active) { gchar err[512]; g_snprintf (err, sizeof(err), "Unable to obtain active connection state for %s", path); network_status (data->client, err); g_main_loop_quit (loop); return; } state = nm_active_connection_get_state (active); //g_print ("Connection %s state: %s\n", path, active_connection_state_to_string(state)); /* If we actually connect, then quit */ if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) { g_main_loop_quit (loop); return; } g_signal_connect (active, "notify::state", G_CALLBACK (active_connection_state_cb), user_data); return; }
/** * Read and process an event from the network mailbox. * * \param[in,out] pi Ping info * * \return 1 if processed an event, 0 if not, and negative error code otherwise */ static int net_mbox_event(ping_info_t *pi) { ExamsgMID mid; static char msg[sizeof(ExamsgNetRqst) + sizeof(Examsg)]; int s; if (network_status() != 0) return 0; s = examsgMboxRecv(EXAMSG_NETMBOX_ID, &mid, sizeof(mid), msg, sizeof(msg)); if (s == 0) /* Nothing to read */ return 0; if (s <= sizeof(ExamsgNetRqst)) { exalog_error("received %d bytes, error %s", s, exa_error_msg(s)); return -EINVAL; } s = network_send(&mid, (ExamsgNetRqst *)msg); if (s < 0) { if (network_manageable(s)) { remember_unsent(&mid, msg, sizeof(msg)); return s; } exalog_error("net mailbox event: error %s", exa_error_msg(s)); return -EIO; } reset_ping(pi); return 1; }
/** * Thread processing network events (coming from other nodes). * * This routine may set the network status to down as a side-effect * of calling network_recv(), and sets said status to up when the * network comes back. * * \param[in] dummy Unused * * \return NULL */ static void net_events_routine(void *dummy) { int dest_mbox; ExamsgMID mid; size_t size; char *msg; int s; exalog_as(EXAMSG_CMSGD_ID); exalog_trace("network events routine started"); while (!quit) { int status = network_status(); bool retry; if (status == -ENETDOWN) { network_waitup(); network_set_status(0); } do { s = network_recv(net_mh, &mid, &msg, &size, &dest_mbox); retry = (s < 0 && network_manageable(s) && s != -ENETDOWN); if (retry) os_sleep(1); } while (retry); /* Succeeded, the network status is ok */ if (s > 0 && status != 0) network_set_status(0); if (s == 0 || s == -ENETDOWN) continue; EXA_ASSERT(s > 0); /* Ping from another node for keepalive */ if (((ExamsgAny *)msg)->type == EXAMSG_PING) { EXA_ASSERT(dest_mbox == EXAMSG_CMSGD_ID); exalog_trace("received an EXAMSG_PING from %u:%s", mid.netid.node, mid.host); continue; } exalog_trace("delivering %" PRIzu " bytes to %d", size, dest_mbox); s = examsgMboxSend(&mid, examsgOwner(net_mh), dest_mbox, msg, size); switch (s) { case -ENXIO: /* The mailbox does not exist (yet). This is not an error: csupd may * not be started yet and we receive an examsg for it. * XXX Doesn't sound too good to me, and we should at least check that * the destination is indeed csupd */ break; case -ENOSPC: mailbox_full(dest_mbox, &mid, (Examsg *)msg); break; default: EXA_ASSERT_VERBOSE(s == size + sizeof(mid), "Error %d delivering message to %d", s, dest_mbox); break; } } }
/** * Thread processing local events (coming from localhost). * * This routine may set the network status to down as a side-effect * of calling network_send(). * * \param dummy Unused * * \return NULL */ static void * local_events_routine(void *dummy) { ping_info_t pi; exalog_trace("local events routine started"); reset_ping(&pi); while (!quit) { int status; int err; /* Must be interruptible because signal TERM triggers quit condition */ err = examsgWaitInterruptible(local_mh, &pi.delay); if (err == -EINTR) continue; if (err == -ETIME) { status = network_status(); if (status == -ENETDOWN) { reset_ping(&pi); continue; } if (unsent.pending) { if (send_unsent() && status != 0) network_set_status(0); } else { send_ping(); adjust_ping(&pi); } continue; } /* Local mailbox messages are more important than network messages * because they may ask for resend, so they are processed first. * * Process as many local messages as possible before considering * network messages so as to avoid sending a new network message * when there still are important messages. */ while (local_mbox_event(&pi) == 1) ; status = network_status(); if (status == -ENETDOWN) continue; if (unsent.pending) { if (send_unsent() && status != 0) network_set_status(0); } else net_mbox_event(&pi); } return NULL; }
/** * Process an event from a local mailbox. * * \param[in,out] pi Ping info * * \return 1 if processed an event 0 if not, negative error code otherwise */ static int local_mbox_event(ping_info_t *pi) { ExamsgMID mid; static Examsg ev; int ev_size; int s; ev_size = examsgRecv(local_mh, &mid, &ev, sizeof(ev)); if (ev_size <= 0) return 0; switch (ev.any.type) { case EXAMSG_EXIT: { exa_nodeset_t dest_nodes; quit = true; exa_nodeset_single(&dest_nodes, mid.netid.node); examsgAckReply(local_mh, &ev, EXA_SUCCESS, mid.id, &dest_nodes); } /* Return 0 because, despite we received a message, we do not want the * main loop to continue to process messages as it is asked to stop now. * So returning 0 juste means here "no need to read anymore messages" */ return 0; case EXAMSG_SUP_PING: if (network_status() == 0) network_special_send(&mid, &ev, ev_size); break; case EXAMSG_ADDNODE: { exa_nodeset_t dest_nodes; examsg_node_info_msg_t *info = (examsg_node_info_msg_t *)&ev; s = network_add_node(info->node_id, info->node_name); exa_nodeset_single(&dest_nodes, mid.netid.node); examsgAckReply(local_mh, &ev, s, mid.id, &dest_nodes); } break; case EXAMSG_DELNODE: { exa_nodeset_t dest_nodes; s = network_del_node(((examsg_node_info_msg_t *)&ev)->node_id); exa_nodeset_single(&dest_nodes, mid.netid.node); examsgAckReply(local_mh, &ev, s, mid.id, &dest_nodes); } break; case EXAMSG_RETRANSMIT_REQ: if (network_status() == 0) { ExamsgRetransmitReq *retreq = (ExamsgRetransmitReq *)&ev; exalog_debug("will send a retransmit request for %d to %u", retreq->count, retreq->node_id); s = network_send_retransmit_req(retreq->node_id, retreq->count); EXA_ASSERT(s == 0); reset_ping(pi); } break; case EXAMSG_RETRANSMIT: if (network_status() == 0) { ExamsgRetransmit *retr = (ExamsgRetransmit *)&ev; exalog_debug("will retransmit messages: %d", retr->count); retransmit(retr->count); reset_ping(pi); } break; case EXAMSG_FENCE: { const examsgd_fencing_req_t *req = &((examsgd_fencing_req_msg_t *)&ev)->request; network_handle_fence_request(req); } break; case EXAMSG_NEW_COMER: reset_ping(pi); break; default: { exa_nodeset_t dest_nodes; exa_nodeset_single(&dest_nodes, mid.netid.node); examsgAckReply(local_mh, &ev, EINVAL, mid.id, &dest_nodes); exalog_error("got unknown message (type %d)", ev.any.type); EXA_ASSERT(false); } break; } return 1; }