bool Layer3::registerVBusmonitor (L_Busmonitor_CallBack * c) { TRACEPRINTF (t, 3, this, "registerVBusmonitor %08X", c); if (!vbusmonitor () && !layer2->openVBusmonitor ()) return 0; vbusmonitor.resize (vbusmonitor () + 1); vbusmonitor[vbusmonitor () - 1].cb = c; TRACEPRINTF (t, 3, this, "registerVBusmontior %08X = 1", c); return 1; }
bool Layer3::deregisterVBusmonitor (L_Busmonitor_CallBack * c) { unsigned i; for (i = 0; i < vbusmonitor (); i++) if (vbusmonitor[i].cb == c) { vbusmonitor[i] = vbusmonitor[vbusmonitor () - 1]; vbusmonitor.resize (vbusmonitor () - 1); if (vbusmonitor () == 0) { layer2->closeVBusmonitor (); } TRACEPRINTF (t, 3, this, "deregisterVBusmonitor %08X = 1", c); return 1; } TRACEPRINTF (t, 3, this, "deregisterVBusmonitor %08X = 0", c); return 0; }
bool Layer3::registerVBusmonitor (L_Busmonitor_CallBack * c) { TRACEPRINTF (t, 3, this, "registerVBusmonitor %08X", c); if (!vbusmonitor ()) { bool have_monitor = false; for (unsigned int i = 0; i < layer2 (); i++) { if (layer2[i]->openVBusmonitor ()) have_monitor = true; } if (! have_monitor) return false; } vbusmonitor.resize (vbusmonitor () + 1); vbusmonitor[vbusmonitor () - 1].cb = c; TRACEPRINTF (t, 3, this, "registerVBusmontior %08X = 1", c); return 1; }
bool Layer3::registerVBusmonitor (L_Busmonitor_CallBack * c) { TRACEPRINTF (t, 3, this, "registerVBusmonitor %08X", c); if (!vbusmonitor ()) for (int i = 0; i < layer2 (); i++) { if (!layer2[i].l2->openVBusmonitor ()) { while (i--) layer2[i].l2->closeVBusmonitor (); TRACEPRINTF (t, 3, this, "registerVBusmontior %08X = 1", c); return 0; } } vbusmonitor.resize (vbusmonitor () + 1); vbusmonitor[vbusmonitor () - 1].cb = c; TRACEPRINTF (t, 3, this, "registerVBusmontior %08X = 1", c); return 1; }
Layer3::~Layer3 () { TRACEPRINTF (t, 3, this, "Close"); Stop (); while (servers ()) delete servers[0]; while (layer2 ()) delete layer2[0]; // the next loops should do exactly nothing while (vbusmonitor ()) deregisterVBusmonitor (vbusmonitor[0].cb); for (unsigned int i = 0; i < tracers (); i++) delete tracers[i]; }
Layer3::~Layer3 () { TRACEPRINTF (t, 3, this, "Close"); Stop (); if (mode) layer2->leaveBusmonitor (); else layer2->Close (); while (vbusmonitor ()) deregisterVBusmonitor (vbusmonitor[0].cb); while (group ()) deregisterGroupCallBack (group[0].cb, group[0].dest); while (individual ()) deregisterIndividualCallBack (individual[0].cb, individual[0].src, individual[0].dest); delete layer2; }
void Layer3::Run (pth_sem_t * stop1) { pth_event_t stop = pth_event (PTH_EVENT_SEM, stop1); unsigned i; while (pth_event_status (stop) != PTH_STATUS_OCCURRED) { LPDU *l = layer2->Get_L_Data (stop); if (!l) continue; if (l->getType () == L_Busmonitor) { L_Busmonitor_PDU *l1, *l2; l1 = (L_Busmonitor_PDU *) l; TRACEPRINTF (t, 3, this, "Recv %s", l1->Decode ()()); for (i = 0; i < busmonitor (); i++) { l2 = new L_Busmonitor_PDU (*l1); busmonitor[i].cb->Get_L_Busmonitor (l2); } for (i = 0; i < vbusmonitor (); i++) { l2 = new L_Busmonitor_PDU (*l1); vbusmonitor[i].cb->Get_L_Busmonitor (l2); } } if (l->getType () == L_Data) { L_Data_PDU *l1; l1 = (L_Data_PDU *) l; if (l1->repeated) { CArray d1 = l1->ToPacket (); for (i = 0; i < ignore (); i++) if (d1 == ignore[i].data) { TRACEPRINTF (t, 3, this, "Repeated discareded"); goto wt; } } l1->repeated = 1; ignore.resize (ignore () + 1); ignore[ignore () - 1].data = l1->ToPacket (); ignore[ignore () - 1].end = getTime () + 1000000; l1->repeated = 0; if (l1->AddrType == IndividualAddress && l1->dest == layer2->getDefaultAddr ()) l1->dest = 0; TRACEPRINTF (t, 3, this, "Recv %s", l1->Decode ()()); if (l1->AddrType == GroupAddress && l1->dest == 0) { for (i = 0; i < broadcast (); i++) broadcast[i].cb->Get_L_Data (new L_Data_PDU (*l1)); } if (l1->AddrType == GroupAddress && l1->dest != 0) { for (i = 0; i < group (); i++) if (group[i].dest == l1->dest || group[i].dest == 0) group[i].cb->Get_L_Data (new L_Data_PDU (*l1)); } if (l1->AddrType == IndividualAddress) { for (i = 0; i < individual (); i++) if (individual[i].dest == l1->dest || individual[i].dest == 0) if (individual[i].src == l1->source || individual[i].src == 0) individual[i].cb->Get_L_Data (new L_Data_PDU (*l1)); } } redel: for (i = 0; i < ignore (); i++) if (ignore[i].end < getTime ()) { ignore.deletepart (i, 1); goto redel; } wt: delete l; } pth_event_free (stop, PTH_FREE_THIS); }
void Layer3::Run (pth_sem_t * stop1) { pth_event_t stop = pth_event (PTH_EVENT_SEM, stop1); unsigned i; running = true; for (i = 0; i < layer2 (); i++) layer2[i].Start (); TRACEPRINTF (t, 3, this, "L3 started"); while (pth_event_status (stop) != PTH_STATUS_OCCURRED) { pth_event_t bufev = pth_event (PTH_EVENT_SEM, &bufsem); pth_event_concat (bufev, stop, NULL); pth_wait (bufev); pth_event_isolate (bufev); if (pth_event_status (bufev) != PTH_STATUS_OCCURRED) { pth_event_free (bufev, PTH_FREE_THIS); continue; } pth_event_free (bufev, PTH_FREE_THIS); pth_sem_dec (&bufsem); LPDU *l = buf.get (); if (!l) continue; if (l->getType () == L_Busmonitor) { L_Busmonitor_PDU *l1, *l2; l1 = (L_Busmonitor_PDU *) l; TRACEPRINTF (t, 3, this, "Recv %s", l1->Decode ()()); for (i = 0; i < busmonitor (); i++) { l2 = new L_Busmonitor_PDU (*l1); busmonitor[i].cb->Send_L_Busmonitor (l2); } for (i = 0; i < vbusmonitor (); i++) { l2 = new L_Busmonitor_PDU (*l1); vbusmonitor[i].cb->Send_L_Busmonitor (l2); } } if (l->getType () == L_Data) { L_Data_PDU *l1; l1 = (L_Data_PDU *) l; if (l1->repeated) { CArray d1 = l1->ToPacket (); for (i = 0; i < ignore (); i++) if (d1 == ignore[i].data) { TRACEPRINTF (t, 3, this, "Repeated discareded"); goto wt; } } l1->repeated = 1; ignore.resize (ignore () + 1); ignore[ignore () - 1].data = l1->ToPacket (); ignore[ignore () - 1].end = getTime () + 1000000; l1->repeated = 0; if (l1->AddrType == IndividualAddress && l1->dest == defaultAddr) l1->dest = 0; TRACEPRINTF (t, 3, this, "Recv %s", l1->Decode ()()); if (l1->AddrType == GroupAddress && l1->dest == 0) { for (i = 0; i < broadcast (); i++) broadcast[i].cb->Send_L_Data (new L_Data_PDU (*l1)); } if (l1->AddrType == GroupAddress && l1->dest != 0) { for (i = 0; i < group (); i++) { Group_Info &grp = group[i]; if (grp.dest == l1->dest || grp.dest == 0) grp.cb->Send_L_Data (new L_Data_PDU (*l1)); } } if (l1->AddrType == IndividualAddress) { for (i = 0; i < individual (); i++) { Individual_Info &indiv = individual[i]; if (indiv.dest == l1->dest || indiv.dest == 0) if (indiv.src == l1->source || indiv.src == 0) indiv.cb->Send_L_Data (new L_Data_PDU (*l1)); } } // finally, send to all (other(?)) L2 interfaces // TODO: filter by addresses send_L_Data(l1); } // ignore[] is ordered, any timed-out items are at the front for (i = 0; i < ignore (); i++) if (ignore[i].end >= getTime ()) break; if (i) ignore.deletepart (0, i); wt: delete l; } TRACEPRINTF (t, 3, this, "L3 stopping"); running = false; for (i = 0; i < layer2 (); i++) layer2[i].Stop (); pth_event_free (stop, PTH_FREE_THIS); }