bool Layer3::registerBusmonitor (L_Busmonitor_CallBack * c) { TRACEPRINTF (t, 3, this, "registerBusmontior %08X", c); if (individual ()) return 0; if (group ()) return 0; if (broadcast ()) return 0; if (mode == 0) { layer2->Close (); if (!layer2->enterBusmonitor ()) { layer2->Open (); return 0; } } mode = 1; busmonitor.resize (busmonitor () + 1); busmonitor[busmonitor () - 1].cb = c; TRACEPRINTF (t, 3, this, "registerBusmontior %08X = 1", c); return 1; }
bool Layer3::deregisterBusmonitor (L_Busmonitor_CallBack * c) { unsigned i; for (i = 0; i < busmonitor (); i++) if (busmonitor[i].cb == c) { busmonitor[i] = busmonitor[busmonitor () - 1]; busmonitor.resize (busmonitor () - 1); if (busmonitor () == 0) for (unsigned int i = 0; i < layer2 (); i++) if (layer2[i]->leaveBusmonitor ()) layer2[i]->Open (); TRACEPRINTF (t, 3, this, "deregisterBusmonitor %08X = 1", c); return 1; } TRACEPRINTF (t, 3, this, "deregisterBusmonitor %08X = 0", c); return 0; }
bool Layer3::registerBusmonitor (L_Busmonitor_CallBack * c) { TRACEPRINTF (t, 3, this, "registerBusmonitor %08X", c); if (!busmonitor()) { bool have_monitor = false; for (unsigned int i = 0; i < layer2 (); i++) if (layer2[i]->Close ()) { if (layer2[i]->enterBusmonitor ()) have_monitor = true; else layer2[i]->Open (); } if (! have_monitor) return false; } busmonitor.resize (busmonitor () + 1); busmonitor[busmonitor () - 1].cb = c; TRACEPRINTF (t, 3, this, "registerBusmontitr %08X = 1", c); return true; }
bool Layer3::registerLayer2 (Layer2 * l2) { TRACEPRINTF (t, 3, this, "registerLayer2 %08X", l2); if (! busmonitor () || ! l2->enterBusmonitor ()) if (! l2->Open ()) { TRACEPRINTF (t, 3, this, "registerLayer2 %08X = 0", l2); return 0; } layer2.resize (layer2() + 1); layer2[layer2 () - 1] = l2; TRACEPRINTF (t, 3, this, "registerLayer2 %08X = 1", l2); return 1; }
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); }