LPDU * TPUARTLayer2Driver::Get_L_Data (pth_event_t stop) { if (stop != NULL) pth_event_concat (getwait, stop, NULL); pth_wait (getwait); if (stop) pth_event_isolate (getwait); if (pth_event_status (getwait) == PTH_STATUS_OCCURRED) { pth_sem_dec (&out_signal); LPDU *l = outqueue.get (); TRACEPRINTF (t, 2, this, "Recv %s", l->Decode ()()); return l; } else return 0; }
LPDU * EIBNetIPTunnel::Get_L_Data (pth_event_t stop) { if (stop != NULL) pth_event_concat (getwait, stop, NULL); pth_wait (getwait); if (stop) pth_event_isolate (getwait); if (pth_event_status (getwait) == PTH_STATUS_OCCURRED) { pth_sem_dec (&outsignal); LPDU *c = outqueue.get (); if (c) TRACEPRINTF (t, 2, this, "Recv %s", c->Decode ()()); return c; } else return 0; }
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); }