/** * @brief Read 1 or more bytes from the I2C slave at the specified memory address * @param device_address The address of the device to read from * @param start_address The memory address to read from * @param data The allocated array to read into * @param data_bytes The number of bytes to read */ void SoftwareI2C::randomRead(char device_address, char start_address, char* data, char data_bytes) { if (data == 0 || data_bytes == 0) return; device_address = device_address & 0xFE; start(); putByte(device_address); if (!getAck()) { return; } putByte(start_address); if (!getAck()) { return; } device_address=device_address | 0x01; start(); putByte(device_address); if (!getAck()) { return; } for ( int x = 0; x < data_bytes; ++x) { data[x] = getByte(); if (x != (data_bytes - 1)) giveAck(); } stop(); }
/** * @brief Write 1 byte to the I2C slave * @param device_address The address of the device to write to * @param byte The data to write */ void SoftwareI2C::write(uint8_t device_address, uint8_t byte) { device_address = device_address & 0xFE; start(); putByte(device_address); getAck(); putByte(byte); getAck(); stop(); }
/** * @brief Write 1 byte to the I2C slave * @param device_address The address of the device to write to * @param byte The data to write */ void SoftwareI2C::write(char device_address, char byte) { device_address = device_address & 0xFE; start(); putByte(device_address); getAck(); putByte(byte); getAck(); stop(); }
/** * @brief Write 1 or more bytes to the I2C slave * @param device_address The address of the device to write to * @param data An array to write the data from * @param data_bytes Number of bytes to write from array */ void SoftwareI2C::write(char device_address, char* data, char data_bytes) { if (data == 0 || data_bytes == 0) return; device_address = device_address & 0xFE; start(); putByte(device_address); getAck(); for ( int x = 0; x < data_bytes; ++x ) { putByte(data[x]); getAck(); } stop(); }
/** * @brief Write 1 or more bytes to the I2C slave at the specified memory address * @param device_address The address of the device to write to * @param start_address The memory address to write to * @param data The data to write * @param data_bytes The number of bytes to write */ void SoftwareI2C::randomWrite(uint8_t device_address, uint8_t start_address, uint8_t* data, uint8_t data_bytes) { if (data == 0 || data_bytes == 0) return; device_address = device_address & 0xFE; start(); putByte(device_address); getAck(); putByte(start_address); getAck(); for ( int x = 0; x <= data_bytes; ++x ) { putByte(data[x]); getAck(); } stop(); }
bufferStruct receiveSendData(bufferStruct buffer){ bufferStruct result; if(getAck(buffer.bufferLength, buffer.buffer) & NEED_ACK > 0){ #if STATE_UART_DEBUG >= 2 uart_putstr ("seAck\r\n"); #endif state = STATE_SENDING_ACK; backupData.bufferLength = buffer.bufferLength; memcpy(backupData.buffer, buffer.buffer, buffer.bufferLength); sendAck(buffer); } else { result.bufferLength = getPayloadLength(buffer.bufferLength, buffer.buffer); memcpy(result.buffer, getPayload(buffer.bufferLength, buffer.buffer), result.bufferLength); #if STATE_UART_DEBUG >= 3 uart_putc('%'); uart_putc(result.bufferLength); uart_putc('%'); for(uint8_t i = 0; i < result.bufferLength; ++i){ uart_putc(result.buffer[i]); } uart_putc('%'); #endif } return result; }
int clientSlidingWindow( UdpSocket &sock, const int max, int message[], int windowSize ) { cerr << "Sliding-window test:" << endl; int lar = -1; // last acknowledgment received int seq = 0; // current seq # int retransmits = 0; if(sock.pollRecvFrom() > 0) { // check for any old acks sock.recvFrom( ( char * ) message, MSGSIZE ); // clean out the socket } vector<int> window(windowSize); for(int i = 0; i < windowSize; i++) { //init window window[i] = -1; } Timer t; while( seq < max) { while(seq - lar <= windowSize && seq < max) { // while seq is within window message[0] = seq; // append seq to message sock.sendTo((char*) message, MSGSIZE); // send message seq++; // increment seq } long lap; t.start(); // timer start while ((lap = t.lap()) < 1500) { if(sock.pollRecvFrom() > 0) { // while not timed out getAck(lar, sock); // check for an ack break; } } if (lap >=1500) { // if no ack seq = lar+1; // reset sequence # retransmits++; } } return retransmits; }
/** * Send a message. * Waits for the firmware to acknowlge and resends the packet * a few timew if not acknowledged. * @param m The message to send * @throw Transport::Exception if never acknowledged. */ void Transport::send(Message *m) { CHECK_THROW_CONFIGURED(); char skip_send = 0; Message* ack = NULL; int transmit_times = 0; short result_code; poll(); while(1) { // We have exceeded our retry numbers if (transmit_times > this->retries) { break; } // Write output if (!skip_send) WriteData(serial, (char*)(m->data), m->total_len); // Wait up to 100 ms for ack for(int i = 0; i<RETRY_DELAY_MS; ++i) { usleep(1000); if( (ack=getAck()) ) break; } // No message - resend if (ack == NULL) { skip_send = 0; //cout << "No message received yet" << endl; transmit_times++; continue; } // Check result code // If the result code is bad, the message was still transmitted // successfully result_code = btou(ack->getPayloadPointer(), 2); if (result_code > 0) { throw new BadAckException(result_code); } else { // Everything's good - return break; } // Other failure transmit_times++; } if( ack == NULL ) { throw new TransportException("Unacknowledged send", TransportException::UNACKNOWLEDGED_SEND); } delete ack; m->is_sent = true; }
/** * @brief Read 1 or more bytes from the I2C slave * @param device_address The address of the device to read from * @param data An allocated array to read the data into * @param data_bytes Number of bytes to read (must be equal to or less then the allocated memory in data) */ void SoftwareI2C::read(char device_address, char* data, char data_bytes) { if (data == 0 || data_bytes == 0) return; device_address = device_address | 0x01; start(); putByte(device_address); getAck(); for (int x = 0; x < data_bytes; ++x) { data[x] = getByte(); if ( x < (data_bytes -1)) { //ack all but the final byte giveAck(); } } stop(); }
// Put a byte across the wire // Return true if the slave acknowledges static boolean putByte(const I2C_ABSTRACT_BUS* bus, uint8_t b){ const I2C_SOFTWARE_BUS* i2c = (const I2C_SOFTWARE_BUS*)bus; int8_t i; for(i=7; i>=0; i--){ if( b & 0x80 ){ sda_high(i2c); }else{ sda_low(i2c); } scl_high(i2c); b <<= 1; scl_low(i2c); } return getAck(i2c); // return ACK value }
void MUXSender(BCSPStack * stack) { Packet * pkt = null ; while(1) { //wait for the slip-sender to be available - (the slip-sender only has one packet //slot rather than a queue to prevent problems with window-rollbacks. if (stack->SLIPInputPacket) SYNCBLKwaitSignal(stack,&stack->SLIPSendAvailableSignal) ; //we prefer to send an unreliable packet if one is available pkt=ASYNCBLKgetPacketFromBuffer(stack,&stack->MUXUnreliableInput) ; //otherwise, we'll take a reliable one if one is available if (!pkt) pkt = ASYNCBLKremoveFirstUnsentPacketFromWindow(stack,&stack->theXMITWindow) ; //the last resort is to send a dedicated ack packet but we only need //to do this if an ack is definitely required if (!pkt) { if (!stack->ackRequired) SYNCBLKwaitSignal(stack,&stack->txackSignal) ; //blocking on the signal has the side-effect of also blocking on the //previous conditions so we'll be woken up by anything stack->ackRequired = false ; pkt = &stack->theAckPacket ; //use the dedicated ack packet } //ok - at this point we have a packet and we're intent on sending it setAck(pkt, stack->txack) ; //set the correct acknowledgement number //add the checksum to the header after setting crc if (stack->configuration->useCRC) setPacketHasCRC(pkt) ; setPacketChecksum(pkt) ; //pass it on to SLIP layer // JBS: no GetTickCount on POSIX // BTRACE5(MUX,"MUX sending pkt %p seq %d ack %d len %d time %d\n",pkt,getSeq(pkt),getAck(pkt),getLength(pkt), GetTickCount() ) ; BTRACE4(MUX,"MUX sending pkt %p seq %d ack %d len %d\n",pkt,getSeq(pkt),getAck(pkt),getLength(pkt)) ; stack->SLIPInputPacket = pkt ; setSignal(stack,&stack->MUXHasPacketForSLIPSignal) ; } }
bufferStruct checkReceiveData(bufferStruct buffer){ rfm12_tick(); //periodic tick function - call that one once in a while switch(state){ case STATE_TIMEOUT: #if STATE_UART_DEBUG >= 2 uart_putstr ("tiOu\r\n"); #endif ++timoutCounter; if(timoutCounter > 5){ #if STATE_UART_DEBUG >= 2 uart_putstr ("tiOuOverl\r\n"); #endif state = STATE_FREE; stopTimer(); timoutCounter = 0; } else { processNack(); } break; case STATE_SENDING_ACK: if(rfm12_tx_status() == STATUS_FREE){ state = STATE_SENDING_DATA; #if STATE_UART_DEBUG >= 2 uart_putstr ("finSeAck\r\n"); #endif bufferStruct result; result.bufferLength = getPayloadLength(backupData.bufferLength, backupData.buffer); memcpy(result.buffer, getPayload(backupData.bufferLength, backupData.buffer), result.bufferLength); uart_putc('%'); uart_putc(result.bufferLength); uart_putc('%'); for(uint8_t i = 0; i < result.bufferLength; ++i){ uart_putc(result.buffer[i]); } uart_putc('%'); return result; } case STATE_SENDING_DATA: if(rfm12_tx_status() == STATUS_FREE){ #if STATE_UART_DEBUG >= 2 uart_putstr ("finSeData\r\n"); #endif state = STATE_FREE; } } //uart_putstr (rfm12_rx_status()); if (rfm12_rx_status() == STATUS_COMPLETE){ bufferStruct tempBuffer; tempBuffer.bufferLength = rfm12_rx_len(); memcpy(tempBuffer.buffer, rfm12_rx_buffer(), tempBuffer.bufferLength); if(validateCrc(tempBuffer)){ #if STATE_UART_DEBUG >= 2 uart_putstr ("crcAck\r\n"); #endif } else { #if STATE_UART_DEBUG >= 2 uart_putstr ("crcNack\r\n"); #endif rfm12_rx_clear(); sendNack(tempBuffer); return buffer; } if(state > STATE_FREE){ if(getAck(tempBuffer.bufferLength, tempBuffer.buffer) & ACK){ #if STATE_UART_DEBUG >= 2 uart_putstr ("rxAck\r\n"); #endif processAck(); } else if(getType(tempBuffer.bufferLength, tempBuffer.buffer) & NACK){ #if STATE_UART_DEBUG >= 2 uart_putstr ("rxNack\r\n"); #endif processNack(); } } if(state == STATE_FREE){ switch(getType(tempBuffer.bufferLength, tempBuffer.buffer)){ case SEND_DATA: #if STATE_UART_DEBUG >= 2 uart_putstr ("send\r\n"); #endif buffer = receiveSendData(tempBuffer); break; // here we should implement the cases of repeating data therefore we would have to know all last data sent // here we should implement the get back to in -> timeframe not yet implemented } } // tell the implementation that the buffer // can be reused for the next data. rfm12_rx_clear(); } return buffer; }
void CAnalogueRepeaterApp::createThread() { CAnalogueRepeaterThread* thread = new CAnalogueRepeaterThread; wxString openId, closeId, beacon1, beacon2; unsigned int speed, freq; wxFloat32 level1, level2; AUDIO_SOURCE openIdSource, closeIdSource, beacon1Source, beacon2Source; getCallsign(openIdSource, openId, closeIdSource, closeId, beacon1Source, beacon1, beacon2Source, beacon2, speed, freq, level1, level2); wxLogInfo(wxT("Open ID source: %d, value: \"%s\", close ID source: %d, value: \"%s\", beacon 1 source: %d, value: \"%s\", beacon 2 source: %d, value: \"%s\", speed: %u WPM, freq: %u Hz, level1: %.3f, level2: %.3f"), int(openIdSource), openId.c_str(), int(closeIdSource), closeId.c_str(), int(beacon1Source), beacon1.c_str(), int(beacon2Source), beacon2.c_str(), speed, freq, level1, level2); IFixedAudioSource* openIdAudio = NULL; IFixedAudioSource* closeIdAudio = NULL; IFixedAudioSource* beacon1Audio = NULL; IFixedAudioSource* beacon2Audio = NULL; switch (openIdSource) { case AS_CW_KEYER: openIdAudio = new CCWKeyer(openId, speed, freq, ANALOGUE_RADIO_SAMPLE_RATE); break; case AS_WAV_FILE: { CWAVFileStore* audio = new CWAVFileStore; bool res = audio->load(openId, ANALOGUE_RADIO_SAMPLE_RATE); if (!res) delete audio; else openIdAudio = audio; } break; } switch (closeIdSource) { case AS_CW_KEYER: closeIdAudio = new CCWKeyer(closeId, speed, freq, ANALOGUE_RADIO_SAMPLE_RATE); break; case AS_WAV_FILE: { CWAVFileStore* audio = new CWAVFileStore; bool res = audio->load(closeId, ANALOGUE_RADIO_SAMPLE_RATE); if (!res) delete audio; else closeIdAudio = audio; } break; } switch (beacon1Source) { case AS_CW_KEYER: beacon1Audio = new CCWKeyer(beacon1, speed, freq, ANALOGUE_RADIO_SAMPLE_RATE); break; case AS_WAV_FILE: { CWAVFileStore* audio = new CWAVFileStore; bool res = audio->load(beacon1, ANALOGUE_RADIO_SAMPLE_RATE); if (!res) delete audio; else beacon1Audio = audio; } break; } switch (beacon2Source) { case AS_CW_KEYER: beacon2Audio = new CCWKeyer(beacon2, speed, freq, ANALOGUE_RADIO_SAMPLE_RATE); break; case AS_WAV_FILE: { CWAVFileStore* audio = new CWAVFileStore; bool res = audio->load(beacon2, ANALOGUE_RADIO_SAMPLE_RATE); if (!res) delete audio; else beacon2Audio = audio; } break; } thread->setCallsign(openIdAudio, closeIdAudio, beacon1Audio, beacon2Audio, level1, level2); wxString radioAck, extAck, batteryAck; unsigned int ack, minimum; wxFloat32 level; AUDIO_SOURCE radioAckSource, extAckSource, batteryAckSource; getAck(radioAckSource, radioAck, extAckSource, extAck, batteryAckSource, batteryAck, speed, freq, level, ack, minimum); wxLogInfo(wxT("Radio ack source: %d, radio ack: \"%s\", network ack source: %d, network ack: \"%s\", battery ack source: %d, battery ack: \"%s\", speed: %u WPM, freq: %u Hz, level: %.3f, ack: %u ms, minimum: %u ms"), int(radioAckSource), radioAck.c_str(), int(extAckSource), extAck.c_str(), int(batteryAckSource), batteryAck.c_str(), speed, freq, level, ack, minimum); IFixedAudioSource* radioAckAudio = NULL; IFixedAudioSource* extAckAudio = NULL; IFixedAudioSource* batteryAckAudio = NULL; switch (radioAckSource) { case AS_CW_KEYER: radioAckAudio = new CCWKeyer(radioAck, speed, freq, ANALOGUE_RADIO_SAMPLE_RATE); break; case AS_WAV_FILE: { CWAVFileStore* audio = new CWAVFileStore; bool res = audio->load(radioAck, ANALOGUE_RADIO_SAMPLE_RATE); if (!res) delete audio; else radioAckAudio = audio; } break; } switch (extAckSource) { case AS_CW_KEYER: extAckAudio = new CCWKeyer(extAck, speed, freq, ANALOGUE_RADIO_SAMPLE_RATE); break; case AS_WAV_FILE: { CWAVFileStore* audio = new CWAVFileStore; bool res = audio->load(extAck, ANALOGUE_RADIO_SAMPLE_RATE); if (!res) delete audio; else extAckAudio = audio; } break; } switch (batteryAckSource) { case AS_CW_KEYER: batteryAckAudio = new CCWKeyer(batteryAck, speed, freq, ANALOGUE_RADIO_SAMPLE_RATE); break; case AS_WAV_FILE: { CWAVFileStore* audio = new CWAVFileStore; bool res = audio->load(extAck, ANALOGUE_RADIO_SAMPLE_RATE); if (!res) delete audio; else batteryAckAudio = audio; } break; } thread->setAck(radioAckAudio, extAckAudio, batteryAckAudio, level, ack, minimum); unsigned int callsignTime, timeout, lockoutTime, hangTime, latchTime; getTimes(callsignTime, timeout, lockoutTime, hangTime, latchTime); thread->setTimes(callsignTime, timeout, lockoutTime, hangTime, latchTime); wxLogInfo(wxT("Times set to: callsign time: %u secs, timeout: %u secs, lockout time: %u secs, hang time: %u secs, latch time: %u secs"), callsignTime, timeout, lockoutTime, hangTime, latchTime); bool tbEnable, ctcssInternal; wxFloat32 tbThreshold, ctcssFreq, ctcssThresh, ctcssLevel; unsigned int ctcssHangTime; ANALOGUE_CTCSS_OUTPUT ctcssOutput; getTones(tbEnable, tbThreshold, ctcssFreq, ctcssInternal, ctcssThresh, ctcssLevel, ctcssHangTime, ctcssOutput); thread->setTones(tbEnable, tbThreshold, ctcssFreq, ctcssInternal, ctcssThresh, ctcssLevel, ctcssHangTime, ctcssOutput); wxLogInfo(wxT("Tones set to: toneburst enable: %u, threshold: %.3f, CTCSS freq: %.1f Hz, internal: %u, threshold: %.3f, level: %.3f, hang time: %u ms, output: %d"), tbEnable, tbThreshold, ctcssFreq, ctcssInternal, ctcssThresh, ctcssLevel, ctcssHangTime * 20U, ctcssOutput); ANALOGUE_CALLSIGN_START callsignAtStart; unsigned int callsignStartDelay; bool callsignAtEnd; ANALOGUE_TIMEOUT_TYPE timeoutType; ANALOGUE_CALLSIGN_HOLDOFF callsignHoldoff; getFeel(callsignAtStart, callsignStartDelay, callsignAtEnd, timeoutType, callsignHoldoff); thread->setFeel(callsignAtStart, callsignStartDelay, callsignAtEnd, timeoutType, callsignHoldoff); wxLogInfo(wxT("Feel set to: callsignAtStart: %d, callsignStartDelay: %u s, callsignAtEnd: %u, timeoutType: %d, callsignHoldoff: %d"), callsignAtStart, callsignStartDelay, callsignAtEnd, timeoutType, callsignHoldoff); wxString readDevice, writeDevice; unsigned int audioDelay; bool deEmphasis, preEmphasis, vogad; getRadio(readDevice, writeDevice, audioDelay, deEmphasis, preEmphasis, vogad); wxLogInfo(wxT("Radio soundcard set to %s:%s, delay: %u ms, de-emphasis: %d, pre-emphasis %d, vogad: %d"), readDevice.c_str(), writeDevice.c_str(), audioDelay * 20U, int(deEmphasis), int(preEmphasis), int(vogad)); if (!readDevice.IsEmpty() && !writeDevice.IsEmpty()) { CSoundCardReaderWriter* soundcard = new CSoundCardReaderWriter(readDevice, writeDevice, ANALOGUE_RADIO_SAMPLE_RATE, ANALOGUE_RADIO_BLOCK_SIZE); soundcard->setCallback(thread, SOUNDCARD_RADIO); bool res = soundcard->open(); if (!res) wxLogError(wxT("Cannot open the radio sound card")); else thread->setRadio(soundcard, audioDelay, deEmphasis, preEmphasis, vogad); } wxString type; unsigned int pttDelay, squelchDelay, cfg; bool pttInvert, squelchInvert; getController(type, cfg, pttDelay, squelchDelay, pttInvert, squelchInvert); wxLogInfo(wxT("Controller set to %s, config: %u, ptt delay: %u ms, squelch delay: %u ms, ptt invert: %d, squelch invert: %d"), type.c_str(), cfg, pttDelay * 20U, squelchInvert * 20U, pttInvert, squelchInvert); CExternalController* controller = NULL; wxString port; if (type.StartsWith(wxT("Velleman K8055 - "), &port)) { unsigned long num; port.ToULong(&num); controller = new CExternalController(new CK8055Controller(num), pttInvert, squelchInvert); } else if (type.StartsWith(wxT("Serial - "), &port)) { controller = new CExternalController(new CSerialLineController(port, cfg), pttInvert, squelchInvert); } else if (type.StartsWith(wxT("Arduino - "), &port)) { controller = new CExternalController(new CArduinoController(port), pttInvert, squelchInvert); #if defined(GPIO) } else if (type.IsSameAs(wxT("GPIO"))) { controller = new CExternalController(new CGPIOController(cfg), pttInvert, squelchInvert); #endif } else { controller = new CExternalController(new CDummyController, pttInvert, squelchInvert); } bool res = controller->open(); if (!res) wxLogError(wxT("Cannot open the hardware interface - %s"), type.c_str()); else thread->setController(controller, pttDelay, squelchDelay); ANALOGUE_EXTERNAL_MODE mode; wxString device; SERIALPIN txPin, rxPin; bool background; getExternal(mode, readDevice, writeDevice, audioDelay, deEmphasis, preEmphasis, vogad, device, txPin, rxPin, background); wxLogInfo(wxT("External mode: %d, soundcard set to %s:%s, delay: %u ms, de-emphasis: %d, pre-emphasis %d, vogad: %u, interface set to %s, tx %d, rx %d, background: %d"), mode, readDevice.c_str(), writeDevice.c_str(), audioDelay * 20U, int(deEmphasis), int(preEmphasis), int(vogad), device.c_str(), txPin, rxPin, int(background)); if (mode != AEM_DISABLED) { CSoundCardReaderWriter* soundcard = new CSoundCardReaderWriter(readDevice, writeDevice, ANALOGUE_RADIO_SAMPLE_RATE, ANALOGUE_RADIO_BLOCK_SIZE); soundcard->setCallback(thread, SOUNDCARD_EXTERNAL); bool res = soundcard->open(); if (!res) { wxLogError(wxT("Cannot open the external sound card")); } else { // This works even for an empty device name CNetworkController* controller = new CNetworkController(device, txPin, rxPin); res = controller->open(); if (!res) wxLogError(wxT("Cannot open serial port - %s"), device.c_str()); else thread->setExternal(mode, soundcard, audioDelay, deEmphasis, preEmphasis, vogad, controller, background); } } bool out1, out2, out3, out4; getOutputs(out1, out2, out3, out4); thread->setOutputs(out1, out2, out3, out4); m_frame->setOutputs(out1, out2, out3, out4); wxLogInfo(wxT("Output 1: %d, output 2: %d, output 3: %d, output 4: %d"), out1, out2, out3, out4); bool dtmfRadio, dtmfExternal; wxString dtmfShutdown, dtmfStartup, dtmfTimeout, dtmfTimeReset, dtmfOutput1, dtmfOutput2, dtmfOutput3, dtmfOutput4; wxString dtmfCommand1, dtmfCommand1Line, dtmfCommand2, dtmfCommand2Line; wxFloat32 dtmfThreshold; getDTMF(dtmfRadio, dtmfExternal, dtmfShutdown, dtmfStartup, dtmfTimeout, dtmfTimeReset, dtmfCommand1, dtmfCommand1Line, dtmfCommand2, dtmfCommand2Line, dtmfOutput1, dtmfOutput2, dtmfOutput3, dtmfOutput4, dtmfThreshold); thread->setDTMF(dtmfRadio, dtmfExternal, dtmfShutdown, dtmfStartup, dtmfTimeout, dtmfTimeReset, dtmfCommand1, dtmfCommand1Line, dtmfCommand2, dtmfCommand2Line, dtmfOutput1, dtmfOutput2, dtmfOutput3, dtmfOutput4, dtmfThreshold); wxLogInfo(wxT("DTMF: Radio: %d, External: %d, Shutdown: %s, Startup: %s, Timeout: %s, Time Reset: %s, Command1: %s = %s, Command2: %s = %s, Output1: %s, Output2: %s, Output3: %s, Output4: %s, Threshold: %f"), dtmfRadio, dtmfExternal, dtmfShutdown.c_str(), dtmfStartup.c_str(), dtmfTimeout.c_str(), dtmfTimeReset.c_str(), dtmfCommand1.c_str(), dtmfCommand1Line.c_str(), dtmfCommand2.c_str(), dtmfCommand2Line.c_str(), dtmfOutput1.c_str(), dtmfOutput2.c_str(), dtmfOutput3.c_str(), dtmfOutput4.c_str(), dtmfThreshold); unsigned int activeHangTime; getActiveHang(activeHangTime); thread->setActiveHang(activeHangTime); wxLogInfo(wxT("Active Hang: time: %u"), activeHangTime); // Convert the worker class into a thread m_thread = new CAnalogueRepeaterThreadHelper(thread); m_thread->start(); }
int main(int argc, char *argv[]) { double probLoss, probCorruption; int sockfd, newsockfd, portno, pid, CWnd; socklen_t clilen; struct sockaddr_in serv_addr, cli_addr; struct Header packetHeader; struct sigaction sa; time_t t; srand((unsigned)time(&t)); if (argc < 5) { fprintf(stderr, "ERROR, missing argument\n"); exit(1); } CWnd = atoi(argv[2]); probLoss = atoi(argv[3]); probCorruption = atoi(argv[4]); sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) error("ERROR opening socket"); memset(&serv_addr, 0, sizeof(serv_addr)); portno = atoi(argv[1]); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(portno); if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) error("ERROR on binding"); int n, loss = 0, corruption = 0, base = 0, nextSeqnum = 0, seq = 0, ack = 0, numUnacked = 0, i, j, k, len, cumAck, sizeCliAddr; char buffer[1024]; char packetBuffer[packetBufferSize][maxPacketSize + 1]; int nxtPtr = 0, nxtFree = 0, count = 0; char unacked[CWnd][maxPacketSize + 1]; struct Header recvAck, data; char filename[1024]; FILE * fp; char packet[maxPacketSize + 1]; int cur; //col 1: 0 unacked, 1 acked or unused //col 2: window seq num //col 3: expected ack int window[CWnd][3]; memset(packet, 0, sizeof(packet)); for (i = 0; i < CWnd; i++) { window[i][0] = 1; window[i][1] = 0; window[i][2] = 0; } memset((struct sigaction *) &sa, 0, sizeof(sa)); sa.sa_handler = setTimeout; sa.sa_flags = SA_SIGINFO; sigaction(SIGALRM, &sa, NULL); //eventually, it seems here that the loop eventually stops sending //packets to the receiver and the receiver is just left hanging... while (1) { memset(buffer, 0, 1024); // read if timeout has not occured if (timeout != 1) { sizeCliAddr = sizeof(cli_addr); n = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *) &cli_addr, &sizeCliAddr); } else errno = EINTR; if (errno == EINTR) { if (timeout == 1) { timeout = 0; k = base + CWnd; for (i = base; i < k; i++) for (j = 0; j < CWnd; j++) if (window[j][0] == 0 && window[j][1] == i) { n = sendto(sockfd, unacked[j], sizeof(unacked[j]), 0, (struct sockaddr *) &cli_addr, sizeof(cli_addr)); if (n < 0) error("ERROR reading from socket"); printf("\nPacket Sent: \n"); printPacket(unacked[j]); break; } alarm(dur); errno = 0; continue; } else error("ERROR reading from socket"); } else if (n < 0) error("ERROR reading from socket"); // if no loss or corruption loss = isHit(probLoss); corruption = isHit(probCorruption); if (loss != 1 && corruption != 1) { // if client asks for file if (getDataLen(buffer) > 0) { //eventually, this block of code never gets called but there are still text left to transmit...a mystery... printPacket(buffer); memset(filename, 0, 1024); getFileName(buffer, filename); printf("File Requested: %s\n", filename); fp = fopen(filename, "r"); if (fp == NULL) error("Failed to open file"); cur = fgetc(fp); len = 0; data.srcPort = ntohs(serv_addr.sin_port); data.destPort = ntohs(cli_addr.sin_port); data.ack = 0; data.flag = 0; i = headerLen; while (1) { if (len < maxPacketSize - headerLen && cur != EOF) { packet[i] = (char)cur; cur = fgetc(fp); len++; i++; } if (len == maxPacketSize - headerLen || cur == EOF) { data.seq = seq; data.dataLen = (short)len; data.checkSum = (short)1; if (cur == EOF) data.flag = 1; memcpy(packet, (struct Header *) &data, headerLen); if (nextSeqnum < base + CWnd) { for (i = 0; i < CWnd; i++) if (window[i][0] == 1) { window[i][0] = 0; window[i][1] = nextSeqnum; window[i][2] = ack + len; n = sendto(sockfd, packet, sizeof(packet), 0, (struct sockaddr *) &cli_addr, sizeof(cli_addr)); if (n < 0) error("ERROR writing to socket"); if (nextSeqnum == base) alarm(dur); printf("\nPacket sent:\n"); printPacket(packet); memcpy(&unacked[i][0], &packet[0], sizeof(packet)); seq += len; ack += len; i = headerLen; len = 0; nextSeqnum++; break; } } else { memcpy(packetBuffer[nxtFree], packet, maxPacketSize); nxtFree++; count++; //adding this helped a bit but not entirely if the file is very large seq += len; ack += len; len = 0; i = headerLen; } memset(packet, 0, sizeof(packet)); if (cur == EOF) { data.flag = 0; break; } } } fclose(fp); fileRequest = 0; } // if client sends ACK else { //this isn't run until all the packets have been sent in the first window //that is, if the CWnd is 10, then nextSeqnum only goes up until 10 and then //the packets go into packetBuffer //the packets in packetBuffer, after all the first set of packets are sent, are now being sent //but what happens after the packets in packetBuffer are all sent? printf("\nPacket Received:\n"); printPacket(buffer); cumAck = getAck(buffer); j = 0; for (i = 0; i < CWnd; i++) { if (window[i][1] >= base && cumAck >= window[i][2] && window[i][0] == 0) { j++; window[i][0] = 1; if (window[i][1] == base) alarm(dur); if (count > 0) { count--; //printf("Sending in the other else branch.\n"); n = sendto(sockfd, packetBuffer[nxtPtr], sizeof(packetBuffer[nxtPtr]), 0, (struct sockaddr *) &cli_addr, sizeof(cli_addr)); if (n < 0) error("ERROR writing to socket"); printPacket(packetBuffer[nxtPtr]); nxtPtr = (nxtPtr + 1) % packetBufferSize; nxtFree = (nxtFree + 1) % packetBufferSize; // TODO: add stuff regarding window } } } base += j; } } // if loss or corruption do nothing else { if (loss == 1 && corruption == 0) printf("Packet Lost:\n"); else if (corruption == 1 && loss == 0) printf("Packet Corrupted:\n"); else printf("Packet Corrupted and Lost:\n"); loss = 0; corruption = 0; printPacket(buffer); } } close(sockfd); return 0; }