/**
* Receives a packet and tries to write the packet into the ringbuffer
*/
void PCAPExporterMem::receive(Packet* packet)
{
    DPRINTFL(MSG_VDEBUG, "PCAPExporterMem::receive() called");
    if (onRestart) {
        DPRINTF("Dropping incoming packet, as attached process is not ready");
        DPRINTFL(MSG_VDEBUG, "PCAPExporterMem::receive() ended");
        packet->removeReference();
        return;
    }
    if (fifoReaderPid == 0) {
        msg(MSG_VDEBUG, "fifoReaderPid = 0...this might happen during reconfiguration");
        DPRINTFL(MSG_VDEBUG, "PCAPExporterMem::receive() ended");
        packet->removeReference();
        return;
    }
    if (restartInterval) {
        if (nextRestart.tv_sec==0) {
            DPRINTFL(MSG_VDEBUG, "PCAPExporterMem::receive(): updating nextRestart");
            nextRestart = packet->timestamp;
            nextRestart.tv_sec += restartInterval;
        } else if (compareTime(nextRestart, packet->timestamp)<0) {
            DPRINTFL(MSG_VDEBUG, "PCAPExporterMem::receive(): restarting process");

            // we need to unregister our signal handlers, as we get race conditions with the signal handler for restarting the process
            unregisterSignalHandlers();
            stopProcess();
            startProcess();
            registerSignalHandlers();
            DPRINTFL(MSG_VDEBUG, "PCAPExporterMem::receive(): updating nextRestart");
            nextRestart.tv_sec += ((packet->timestamp.tv_sec-nextRestart.tv_sec)/restartInterval+1)*restartInterval;
        }
    }

    if (writeIntoMemory(packet)) {
        statPktsForwarded++;
        statBytesForwarded += packet->data_length;
        DPRINTFL(MSG_VDEBUG, "Wrote packet at pos %u", *nextWrite);
    } else {
        batchUpdate();

        statPktsDropped++;
        statBytesDropped += packet->data_length;
        DPRINTFL(MSG_VDEBUG, "PCAPExporterMem::receive(): dropped packet");
    }
    packet->removeReference();
    DPRINTFL(MSG_VDEBUG, "PCAPExporterMem::receive() ended");
}
void PCAPExporterPipe::performShutdown()
{
	unregisterSignalHandlers();
	stopProcess();
}
/**
 * Writes a packet into the pipe
 */
void PCAPExporterPipe::receive(Packet* packet)
{
	DPRINTFL(MSG_VDEBUG, "PCAPExporterPipe::receive() called");
	if (onRestart){
		 DPRINTF("Dropping incoming packet, as attached process is not ready");
		 DPRINTFL(MSG_VDEBUG, "PCAPExporterPipe::receive() ended");
		 packet->removeReference();
		 return;
	}
	if (fifoReaderPid == 0){
		 msg(MSG_VDEBUG, "fifoReaderPid = 0...this might happen during reconfiguration");
		 DPRINTFL(MSG_VDEBUG, "PCAPExporterPipe::receive() ended");
		 packet->removeReference();
		 return;
	}
	if (restartInterval) {
		if (nextRestart.tv_sec==0) {
			DPRINTFL(MSG_VDEBUG, "PCAPExporterPipe::receive(): updating nextRestart");
			nextRestart = packet->timestamp;
			struct timeval tv = { restartInterval/1000, (restartInterval % 1000)*1000 };
			timeval_add(&nextRestart, &tv);
		} else if (compareTime(nextRestart, packet->timestamp)<0) {
			DPRINTFL(MSG_VDEBUG, "PCAPExporterPipe::receive(): restarting process");

			// we need to unregister our signal handlers, as we get race conditions with the signal handler for restarting the process
			unregisterSignalHandlers();
			stopProcess();
			startProcess();
			registerSignalHandlers();
			DPRINTFL(MSG_VDEBUG, "PCAPExporterPipe::receive(): updating nextRestart");
			timeval tvdiff;
			timeval_subtract(&tvdiff, &packet->timestamp, &nextRestart);
			uint32_t msdiff = tvdiff.tv_sec*1000+tvdiff.tv_usec/1000;
			uint32_t mswait = (msdiff/restartInterval+1)*restartInterval;
			tvdiff.tv_sec = mswait/1000;
			tvdiff.tv_usec = (mswait%1000)*1000;
			timeval_add(&nextRestart, &tvdiff);
		}
	}

	// write packet
	static struct pcap_pkthdr packetHeader;
	packetHeader.ts = packet->timestamp;
	packetHeader.caplen = packet->data_length;
	packetHeader.len = packet->pcapPacketLength;
	struct iovec wvec[2];
	wvec[0].iov_base = &packetHeader;
	wvec[0].iov_len = sizeof(packetHeader);
	wvec[1].iov_base = packet->data;
	wvec[1].iov_len = packetHeader.caplen;
	if (writev(pcapFile, wvec, 2)!=(ssize_t)(sizeof(packetHeader)+packetHeader.caplen)) {
		if (errno==EAGAIN) {
			// pipe is full, drop packet
			statBytesDropped += packet->data_length;
			statPktsDropped++;
		} else
			THROWEXCEPTION("PCAPExporterPipe: failed to write, error %u (%s)", errno, strerror(errno));
	} else {
		statBytesForwarded += packet->data_length;
		statPktsForwarded++;
	}

	packet->removeReference();
	DPRINTFL(MSG_VDEBUG, "PCAPExporterPipe::receive() ended");
}
void PCAPExporterMem::performShutdown()
{
    unregisterSignalHandlers();
    stopProcess();
    msg(MSG_INFO, "PCAPExporterMem: sent %llu packets, dropped %llu packets", statPktsForwarded, statPktsDropped);
}
void NcursesEditorView::stop()
{
    unregisterSignalHandlers();
    echo();
    endwin();
}