kopia lustrzana https://github.com/jamescoxon/dl-fldigi
				
				
				
			PSKMAIL/ARQ socket
* rewrite of arq_io.cxx with assistance of Remi
    - more clearly define use of various variable mutex
    - added mutex blocks to TLF interface
    - changed from ::lock ::unlock to
      guard_lock usage.
  * added command line switch
      --debug-pskmail
    which enables verbose time-tagged logging for
    ARQ and PSKMAIL events
  * added guard_lock to debug methods
			
			
				pull/1/head
			
			
		
							rodzic
							
								
									6e16b41620
								
							
						
					
					
						commit
						0f5ede7efa
					
				|  | @ -23,7 +23,7 @@ | |||
| #ifndef _DEBUG_H_ | ||||
| #define _DEBUG_H_ | ||||
| 
 | ||||
| #define DEBUG_PSKMAIL 0 | ||||
| #define DEBUG_PSKMAIL 1 | ||||
| 
 | ||||
| #include "util.h" | ||||
| 
 | ||||
|  | @ -86,6 +86,8 @@ unused__ static uint32_t log_source_ = debug::LOG_OTHER; | |||
| 
 | ||||
| #define LOG_SET_SOURCE(source__) log_source_ = source__ | ||||
| 
 | ||||
| extern bool	debug_pskmail; | ||||
| 
 | ||||
| #endif // _DEBUG_H_
 | ||||
| 
 | ||||
| // Local Variables:
 | ||||
|  |  | |||
							
								
								
									
										10
									
								
								src/main.cxx
								
								
								
								
							
							
						
						
									
										10
									
								
								src/main.cxx
								
								
								
								
							|  | @ -655,6 +655,9 @@ void generate_option_help(void) { | |||
| 	     << "  --debug-level LEVEL\n" | ||||
| 	     << "    Set the event log verbosity\n\n" | ||||
| 
 | ||||
| 	     << "  --debug-pskmail\n" | ||||
| 	     << "    Enable logging for pskmail / arq events\n\n" | ||||
| 
 | ||||
| 	     << "  --version\n" | ||||
| 	     << "    Print version information\n\n" | ||||
| 
 | ||||
|  | @ -754,7 +757,7 @@ int parse_args(int argc, char **argv, int& idx) | |||
| #if USE_PORTAUDIO | ||||
|                OPT_FRAMES_PER_BUFFER, | ||||
| #endif | ||||
| 	       OPT_NOISE, OPT_DEBUG_LEVEL, | ||||
| 	       OPT_NOISE, OPT_DEBUG_LEVEL, OPT_DEBUG_PSKMAIL, | ||||
|                OPT_EXIT_AFTER, | ||||
|                OPT_DEPRECATED, OPT_HELP, OPT_VERSION, OPT_BUILD_INFO }; | ||||
| 
 | ||||
|  | @ -807,6 +810,7 @@ int parse_args(int argc, char **argv, int& idx) | |||
| 
 | ||||
| 		{ "noise", 0, 0, OPT_NOISE }, | ||||
| 		{ "debug-level",   1, 0, OPT_DEBUG_LEVEL }, | ||||
| 		{ "debug-pskmail", 0, 0, OPT_DEBUG_PSKMAIL }, | ||||
| 
 | ||||
| 		{ "help",	   0, 0, OPT_HELP }, | ||||
| 		{ "version",	   0, 0, OPT_VERSION }, | ||||
|  | @ -1006,6 +1010,10 @@ int parse_args(int argc, char **argv, int& idx) | |||
| 		} | ||||
| 			break; | ||||
| 
 | ||||
| 		case OPT_DEBUG_PSKMAIL: | ||||
| 			debug_pskmail = true; | ||||
| 			break; | ||||
| 
 | ||||
| 		case OPT_DEPRECATED: | ||||
| 			cerr << "W: the --" << longopts[longindex].name | ||||
| 			     << " option has been deprecated and will be removed in a future version\n"; | ||||
|  |  | |||
|  | @ -3,12 +3,14 @@ | |||
| //
 | ||||
| // support for ARQ server/client system such as pskmail and fl_arq
 | ||||
| //
 | ||||
| // Copyright (C) 2006-2010
 | ||||
| // Copyright (C) 2006-2013
 | ||||
| //		Dave Freese, W1HKJ
 | ||||
| // Copyright (C) 2008-2010
 | ||||
| // Copyright (C) 2008-2013
 | ||||
| //		Stelios Bounanos, M0GLD
 | ||||
| // Copyright (C) 2009-2010
 | ||||
| // Copyright (C) 2009-2013
 | ||||
| //		John Douyere, VK2ETA
 | ||||
| // Copyright (c) 2013
 | ||||
| //		Remi Chateauneu, F4ECW
 | ||||
| //
 | ||||
| // This file is part of fldigi.
 | ||||
| //
 | ||||
|  | @ -66,9 +68,7 @@ LOG_FILE_SOURCE(debug::LOG_ARQCONTROL); | |||
| 
 | ||||
| using namespace std; | ||||
| 
 | ||||
| // ============================================================================
 | ||||
| // Implementation using thread vice the fldigi timeout facility
 | ||||
| // ============================================================================
 | ||||
| // =====================================================================
 | ||||
| static pthread_t arq_thread; | ||||
| static pthread_mutex_t arq_mutex = PTHREAD_MUTEX_INITIALIZER; | ||||
| static pthread_mutex_t arq_rx_mutex = PTHREAD_MUTEX_INITIALIZER; | ||||
|  | @ -80,10 +80,19 @@ static bool arq_exit = false; | |||
| static bool arq_enabled; | ||||
| static bool abort_flag = false; | ||||
| 
 | ||||
| static string tosend = ""; | ||||
| static string enroute = ""; | ||||
| //======================================================================
 | ||||
| // test code for pskmail eol issues
 | ||||
| /// Any access to shared variables must be protected.
 | ||||
| static string tosend = "";   // Protected by tosend_mutex
 | ||||
| static string enroute = "";  // Protected by tosend_mutex
 | ||||
| 
 | ||||
| static string arqtext = "";  // Protected by arq_rx_mutex
 | ||||
| static string txstring = ""; // Protected by arq_rx_mutex
 | ||||
| static size_t pText;         // Protected by arq_rx_mutex
 | ||||
| bool arq_text_available = false; // Protected by arq_rx_mutex
 | ||||
| // Beware 'arq_text_available' is accessed by other modules.
 | ||||
| 
 | ||||
| static bool bSend0x06 = false; // Protected by arq_rx_mutex
 | ||||
| 
 | ||||
| // =====================================================================
 | ||||
| 
 | ||||
| static const char *asc[128] = { | ||||
| 	"<NUL>", "<SOH>", "<STX>", "<ETX>", | ||||
|  | @ -140,12 +149,6 @@ string noctrl(string src) | |||
| 
 | ||||
| //======================================================================
 | ||||
| 
 | ||||
| static string arqtext; | ||||
| size_t pText; | ||||
| 
 | ||||
| bool arq_text_available = false; | ||||
| string txstring; | ||||
| 
 | ||||
| extern void parse_arqtext(string &toparse); | ||||
| 
 | ||||
| static void set_button(Fl_Button* button, bool value) | ||||
|  | @ -162,10 +165,12 @@ void ParseMode(string src) | |||
| 			int ret = sscanf( src.substr(7, src.length() - 7).c_str(), "%d", &msecs); | ||||
| 			if (ret != 1 || msecs < 10 || msecs > 20000) msecs = 100; | ||||
| 		} | ||||
| LOG_INFO("%s %5.2f sec", "ARQ tune on", msecs/1000.0); | ||||
| 		if (debug_pskmail) | ||||
| 			LOG_INFO("%s %5.2f sec", "ARQ tune on", msecs/1000.0); | ||||
| 		trx_tune(); | ||||
| 		MilliSleep(msecs); | ||||
| LOG_INFO("%s", "ARQ tune off"); | ||||
| 		if (debug_pskmail) | ||||
| 			LOG_INFO("%s", "ARQ tune off"); | ||||
| 		trx_receive(); | ||||
| 		return; | ||||
| 	} | ||||
|  | @ -175,11 +180,13 @@ LOG_INFO("%s", "ARQ tune off"); | |||
| 			int ret = sscanf( src.substr(7, src.length() - 7).c_str(), "%d", &msecs); | ||||
| 			if (ret != 1 || msecs < 10 || msecs > 20000) msecs = 100; | ||||
| 		} | ||||
| LOG_INFO("%s %5.2f sec", "ARQ set ptt on", msecs/1000.0); | ||||
| 		if (debug_pskmail) | ||||
| 			LOG_INFO("%s %5.2f sec", "ARQ set ptt on", msecs/1000.0); | ||||
| 		push2talk->set(true); | ||||
| 		REQ(&waterfall::set_XmtRcvBtn, wf, true); | ||||
| 		MilliSleep(msecs); | ||||
| LOG_INFO("%s", "ARQ set ptt off"); | ||||
| 		if (debug_pskmail) | ||||
| 			LOG_INFO("%s", "ARQ set ptt off"); | ||||
| 		push2talk->set(false); | ||||
| 		REQ(&waterfall::set_XmtRcvBtn, wf, false); | ||||
| 		return; | ||||
|  | @ -190,7 +197,8 @@ LOG_INFO("%s", "ARQ set ptt off"); | |||
| 				while (trx_state != STATE_RX) { | ||||
| 					MilliSleep(10); | ||||
| 				} | ||||
| LOG_INFO("Setting modem to %s", mode_info[i].pskmail_name); | ||||
| 				if (debug_pskmail) | ||||
| 					LOG_INFO("Setting modem to %s", mode_info[i].pskmail_name); | ||||
| 				REQ_SYNC(init_modem_sync, mode_info[i].mode, 0); | ||||
| 				break; | ||||
| 			} | ||||
|  | @ -201,10 +209,12 @@ LOG_INFO("Setting modem to %s", mode_info[i].pskmail_name); | |||
| void ParseRSID(string src) | ||||
| { | ||||
| 	if (src == "ON") { | ||||
| 		if (debug_pskmail) | ||||
| 			LOG_INFO("%s", "RsID turned ON"); | ||||
| 		REQ(set_button, btnRSID, 1); | ||||
| 	} | ||||
| 	if (src == "OFF") { | ||||
| 		if (debug_pskmail) | ||||
| 			LOG_INFO("%s", "RsID turned OFF"); | ||||
| 		REQ(set_button, btnRSID, 0); | ||||
| 	} | ||||
|  | @ -214,10 +224,12 @@ void ParseRSID(string src) | |||
| void ParseTxRSID(string src) | ||||
| { | ||||
| 	if (src == "ON") { | ||||
| 		if (debug_pskmail) | ||||
| 			LOG_INFO("%s", "TxRsID turned ON"); | ||||
| 		REQ(set_button, btnTxRSID, 1); | ||||
| 	} | ||||
| 	if (src == "OFF") { | ||||
| 		if (debug_pskmail) | ||||
| 			LOG_INFO("%s", "TxRsID turned OFF"); | ||||
| 		REQ(set_button, btnTxRSID, 0); | ||||
| 	} | ||||
|  | @ -231,14 +243,12 @@ static	string strSubCmd; | |||
| 
 | ||||
| 	if (toparse.empty()) return; | ||||
| 
 | ||||
| if (DEBUG_PSKMAIL) | ||||
| 	LOG_INFO("Arq text: %s", noctrl(toparse).c_str()); | ||||
| else | ||||
| 	LOG_VERBOSE("Arq text: %s", noctrl(toparse).c_str()); | ||||
| 
 | ||||
| 	idxCmd = toparse.find("<cmd>"); | ||||
| 	idxCmdEnd = toparse.find("</cmd>"); | ||||
| 
 | ||||
| 	if (idxCmd != string::npos && debug_pskmail) | ||||
| 		LOG_INFO("Parsing: %s", noctrl(toparse).c_str()); | ||||
| 
 | ||||
| 	while ( idxCmd != string::npos && idxCmdEnd != string::npos && idxCmdEnd > idxCmd ) { | ||||
| 
 | ||||
| 		strCmdText = toparse.substr(idxCmd + 5, idxCmdEnd - idxCmd - 5); | ||||
|  | @ -315,11 +325,9 @@ else | |||
| 
 | ||||
| #define TIMEOUT 180 // 3 minutes
 | ||||
| 
 | ||||
| bool bSend0x06 = false; | ||||
| 
 | ||||
| //-----------------------------------------------------------------------------
 | ||||
| //======================================================================
 | ||||
| // Gmfsk ARQ file i/o used only on Linux
 | ||||
| //-----------------------------------------------------------------------------
 | ||||
| //======================================================================
 | ||||
| // checkTLF
 | ||||
| // look for files named
 | ||||
| //	TLFfldigi ==> tlfio is true and
 | ||||
|  | @ -348,14 +356,16 @@ static	string TLFlogname; | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| bool TLF_arqRx() | ||||
| static bool TLF_arqRx() | ||||
| { | ||||
| 	/// The mutex is automatically unlocked when returning.
 | ||||
| 	guard_lock arq_rx_lock(&arq_rx_mutex); | ||||
| #if defined(__WOE32__) || defined(__APPLE__) | ||||
| 	return false; | ||||
| #else | ||||
| 	time_t start_time, prog_time; | ||||
| 	static char mailline[1000]; | ||||
| 	static string sAutoFile; | ||||
| 	static string sAutoFile(""); | ||||
| 	sAutoFile.assign(PskMailDir); | ||||
| 	sAutoFile.append("gmfsk_autofile"); | ||||
| 
 | ||||
|  | @ -386,8 +396,6 @@ bool TLF_arqRx() | |||
| 			return true; | ||||
| 		} | ||||
| 
 | ||||
| 		pthread_mutex_lock (&arq_rx_mutex); | ||||
| 
 | ||||
| 		if (arqtext.empty() && !txstring.empty()) { | ||||
| 			arqtext = txstring; | ||||
| 			if (mailserver && progdefaults.PSKmailSweetSpot) | ||||
|  | @ -398,22 +406,19 @@ bool TLF_arqRx() | |||
| 			start_tx(); | ||||
| 			txstring.clear(); | ||||
| 		} | ||||
| 
 | ||||
| 		pthread_mutex_unlock (&arq_rx_mutex); | ||||
| 
 | ||||
| 	} | ||||
| 	return true; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| //-----------------------------------------------------------------------------
 | ||||
| //======================================================================
 | ||||
| // Auto transmit of file contained in WRAP_auto_dir
 | ||||
| //-----------------------------------------------------------------------------
 | ||||
| //======================================================================
 | ||||
| bool WRAP_auto_arqRx() | ||||
| { | ||||
| 	time_t start_time, prog_time; | ||||
| 	static char mailline[1000]; | ||||
| 	static string sAutoFile; | ||||
| 	static string sAutoFile(""); | ||||
| 	sAutoFile.assign(FLMSG_WRAP_auto_dir); | ||||
| 	sAutoFile.append("wrap_auto_file"); | ||||
| 
 | ||||
|  | @ -425,6 +430,8 @@ bool WRAP_auto_arqRx() | |||
| 		autofile.open(sAutoFile.c_str()); | ||||
| 	} | ||||
| 	if(autofile) { | ||||
| 		/// Mutex is unlocked when leaving the block.
 | ||||
| 		guard_lock arq_rx_lock(&arq_rx_mutex); | ||||
| 		txstring.clear(); | ||||
| 		time(&start_time); | ||||
| 		while (!autofile.eof()) { | ||||
|  | @ -458,9 +465,9 @@ bool WRAP_auto_arqRx() | |||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| //-----------------------------------------------------------------------------
 | ||||
| //======================================================================
 | ||||
| // Socket ARQ i/o used on all platforms
 | ||||
| //-----------------------------------------------------------------------------
 | ||||
| //======================================================================
 | ||||
| 
 | ||||
| #define ARQLOOP_TIMING 100 // msec
 | ||||
| #define CLIENT_TIMEOUT 5 // timeout after N secs
 | ||||
|  | @ -470,7 +477,7 @@ static string errstring; | |||
| 
 | ||||
| static pthread_t* arq_socket_thread = 0; | ||||
| ARQ_SOCKET_Server* ARQ_SOCKET_Server::inst = 0; | ||||
| static std::vector<ARQCLIENT> arqclient; | ||||
| static std::vector<ARQCLIENT> arqclient; // Protected by arq_mutex
 | ||||
| 
 | ||||
| void arq_run(Socket); | ||||
| 
 | ||||
|  | @ -563,6 +570,11 @@ void* ARQ_SOCKET_Server::thread_func(void*) | |||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	{ | ||||
| 	/// Mutex is unlocked when leaving the block.
 | ||||
| 		guard_lock arq_lock(&arq_mutex); | ||||
| 
 | ||||
| 		if (!arqclient.empty()) { | ||||
| 			vector<ARQCLIENT>::iterator p = arqclient.begin(); | ||||
| 			while (p != arqclient.end()) { | ||||
|  | @ -574,12 +586,16 @@ void* ARQ_SOCKET_Server::thread_func(void*) | |||
| 				p++; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	inst->server_socket->close(); | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| void arq_reset() | ||||
| { | ||||
| 	/// Mutex is unlocked when returning from function
 | ||||
| 	guard_lock arq_rx_lock(&arq_rx_mutex); | ||||
| 	arqmode = mailserver = mailclient = false; | ||||
| 	txstring.clear(); | ||||
| 	arqtext.clear(); | ||||
|  | @ -589,7 +605,8 @@ void arq_reset() | |||
| 
 | ||||
| void arq_run(Socket s) | ||||
| { | ||||
| 	pthread_mutex_lock (&arq_mutex); | ||||
| 	/// Mutex is unlocked when returning from function
 | ||||
| 	guard_lock arq_lock(&arq_mutex); | ||||
| 	struct timeval t = { 0, 20000 }; | ||||
| 	s.set_timeout(t); | ||||
| 	s.set_nonblocking(); | ||||
|  | @ -606,11 +623,12 @@ void arq_run(Socket s) | |||
| 		p++; | ||||
| 	} | ||||
| 	LOG_INFO("%s", outs.str().c_str()); | ||||
| 	pthread_mutex_unlock (&arq_mutex); | ||||
| } | ||||
| 
 | ||||
| void WriteARQsocket(unsigned char* data, size_t len) | ||||
| { | ||||
| 	/// Mutex is unlocked when returning from function
 | ||||
| 	guard_lock arq_lock(&arq_mutex); | ||||
| 	if (arqclient.empty()) return; | ||||
| 	static string instr; | ||||
| 	instr.clear(); | ||||
|  | @ -644,12 +662,13 @@ void WriteARQsocket(unsigned char* data, size_t len) | |||
| 
 | ||||
| void test_arq_clients() | ||||
| { | ||||
| 	/// Mutex is unlocked when returning from function
 | ||||
| 	guard_lock arq_lock(&arq_mutex); | ||||
| 	if (arqclient.empty()) return; | ||||
| 	static string instr; | ||||
| 	instr.clear(); | ||||
| 	vector<ARQCLIENT>::iterator p; | ||||
| 	p = arqclient.begin(); | ||||
| 	pthread_mutex_lock (&arq_mutex); | ||||
| 	time_t now; | ||||
| 	while (p != arqclient.end()) { | ||||
| 		if (difftime(now = time(0), (*p).keep_alive) > CLIENT_TIMEOUT) { | ||||
|  | @ -673,13 +692,13 @@ void test_arq_clients() | |||
| 		} | ||||
| 	} | ||||
| 	if (arqclient.empty()) arq_reset(); | ||||
| 
 | ||||
| 	pthread_mutex_unlock (&arq_mutex); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| bool Socket_arqRx() | ||||
| { | ||||
| 	{ | ||||
| 	/// Mutex is unlocked when leaving block
 | ||||
| 		guard_lock arq_lock(&arq_mutex); | ||||
| 		if (arqclient.empty()) return false; | ||||
| 
 | ||||
| 		static string instr; | ||||
|  | @ -687,8 +706,6 @@ bool Socket_arqRx() | |||
| 		size_t n = 0; | ||||
| 		instr.clear(); | ||||
| 
 | ||||
| 	pthread_mutex_lock (&arq_mutex); | ||||
| 
 | ||||
| 		while (p != arqclient.end()) { | ||||
| 			try { | ||||
| 				(*p).sock.wait(0); | ||||
|  | @ -711,9 +728,11 @@ bool Socket_arqRx() | |||
| 			} | ||||
| 		} | ||||
| 		if (arqclient.empty()) arq_reset(); | ||||
| 	} | ||||
| 
 | ||||
| 	pthread_mutex_unlock (&arq_mutex); | ||||
| 
 | ||||
| 	{ | ||||
| 	/// Mutex is unlocked when leaving block
 | ||||
| 		guard_lock arq_rx_lock(&arq_rx_mutex); | ||||
| 		if (!txstring.empty()) parse_arqtext(txstring); | ||||
| 
 | ||||
| 		if (abort_flag) { | ||||
|  | @ -722,21 +741,24 @@ bool Socket_arqRx() | |||
| 			return true; | ||||
| 		} | ||||
| 
 | ||||
| 	if (bSend0x06 || txstring.empty()) return false; | ||||
| 		{ | ||||
| 
 | ||||
| 	pthread_mutex_lock (&arq_rx_mutex); | ||||
| 		if (bSend0x06 || txstring.empty()) return false; | ||||
| 
 | ||||
| 		if (arqtext.empty()) { | ||||
| 			arqtext.assign(txstring); | ||||
| 		LOG_INFO("Assigned tx text: %s", noctrl(txstring).c_str()); | ||||
| //			if (debug_pskmail)
 | ||||
| //				LOG_INFO("Assigned tx text: %s", noctrl(txstring).c_str());
 | ||||
| 			pText = 0; | ||||
| 			if (mailserver && progdefaults.PSKmailSweetSpot) | ||||
| 				active_modem->set_freq(progdefaults.PSKsweetspot); | ||||
| 			start_tx(); | ||||
| 		} else { | ||||
| 			arqtext.append(txstring); | ||||
| 		LOG_INFO("Appended tx text: %s", noctrl(txstring).c_str()); | ||||
| //			if (debug_pskmail)
 | ||||
| //				LOG_INFO("Appended tx text: %s", noctrl(txstring).c_str());
 | ||||
| 			if (trx_state != STATE_TX) { | ||||
| 				if (debug_pskmail) | ||||
| 					LOG_INFO("%s","Restarting TX"); | ||||
| 				start_tx(); | ||||
| 			} | ||||
|  | @ -745,34 +767,30 @@ bool Socket_arqRx() | |||
| 
 | ||||
| 		arq_text_available = true; | ||||
| 		active_modem->set_stopflag(false); | ||||
| 
 | ||||
| 	pthread_mutex_unlock (&arq_rx_mutex); | ||||
| 
 | ||||
| 		} | ||||
| 	} | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| // ============================================================================
 | ||||
| //======================================================================
 | ||||
| // Implementation using thread vice the fldigi timeout facility
 | ||||
| // ============================================================================
 | ||||
| //======================================================================
 | ||||
| 
 | ||||
| void WriteARQ(unsigned char data) | ||||
| { | ||||
| 	pthread_mutex_lock (&tosend_mutex); | ||||
| 	guard_lock tosend_lock(&tosend_mutex); | ||||
| 	tosend += data; | ||||
| 	pthread_mutex_unlock (&tosend_mutex); | ||||
| 	return; | ||||
| } | ||||
| 
 | ||||
| void WriteARQ(const char *data) | ||||
| { | ||||
| 	pthread_mutex_lock (&tosend_mutex); | ||||
| 	guard_lock tosend_lock(&tosend_mutex); | ||||
| 	tosend.append(data); | ||||
| 	pthread_mutex_unlock (&tosend_mutex); | ||||
| 	return; | ||||
| } | ||||
| 
 | ||||
| static void *arq_loop(void *args) | ||||
| { | ||||
| 	static unsigned char szACK = 0x06; | ||||
| 	SET_THREAD_ID(ARQ_TID); | ||||
| 
 | ||||
| 	for (;;) { | ||||
|  | @ -782,27 +800,23 @@ static void *arq_loop(void *args) | |||
| 
 | ||||
| 		test_arq_clients(); | ||||
| 
 | ||||
| 		{ | ||||
| 		/// Mutex is unlocked when exiting block
 | ||||
| 			guard_lock tosend_lock(&tosend_mutex); | ||||
| 			enroute.clear(); | ||||
| 		pthread_mutex_lock(&tosend_mutex); | ||||
| 			if (!tosend.empty()) { | ||||
| 				enroute = tosend; | ||||
| 				tosend.clear(); | ||||
| 			} | ||||
| 		pthread_mutex_unlock(&tosend_mutex); | ||||
| 
 | ||||
| 			if (!enroute.empty()) { | ||||
| 			pthread_mutex_lock (&arq_mutex); | ||||
| 				WriteARQsocket((unsigned char*)enroute.c_str(), enroute.length()); | ||||
| 			pthread_mutex_unlock (&arq_mutex); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if (bSend0x06) { | ||||
| 			pthread_mutex_lock (&arq_mutex); | ||||
| 			string xmtdone; | ||||
| 			xmtdone += 0x06; | ||||
| 			WriteARQsocket((unsigned char*)xmtdone.c_str(), xmtdone.length()); | ||||
| 			WriteARQsocket(&szACK, 1); | ||||
| 			bSend0x06 = false; | ||||
| 			pthread_mutex_unlock (&arq_mutex); | ||||
| 		} | ||||
| 
 | ||||
| 
 | ||||
|  | @ -853,9 +867,10 @@ void arq_close(void) | |||
| 
 | ||||
| int arq_get_char() | ||||
| { | ||||
| 	/// Mutex is unlocked when returning from function
 | ||||
| 	guard_lock arq_rx_lock(&arq_rx_mutex); | ||||
| 	int c = 0; | ||||
| 	if (arq_text_available) { | ||||
| 		pthread_mutex_lock (&arq_rx_mutex); | ||||
| 		if (pText != arqtext.length()) { | ||||
| 			c = arqtext[pText++] & 0xFF; | ||||
| 		} else { | ||||
|  | @ -865,30 +880,33 @@ int arq_get_char() | |||
| 			arq_text_available = false; | ||||
| 			c = GET_TX_CHAR_ETX; | ||||
| 		} | ||||
| 		pthread_mutex_unlock (&arq_rx_mutex); | ||||
| 	} | ||||
| 	return c; | ||||
| } | ||||
| 
 | ||||
| //======================================================================
 | ||||
| // following function used if the T/R button is pressed to stop a transmission
 | ||||
| // that is servicing the ARQ text buffer.  It allows the ARQ client to reset
 | ||||
| // itself properly
 | ||||
| 
 | ||||
| //======================================================================
 | ||||
| void AbortARQ() { | ||||
| 	pthread_mutex_lock (&arq_mutex); | ||||
| 	/// Mutex is unlocked when returning from function
 | ||||
| 	guard_lock arq_lock(&arq_rx_mutex); | ||||
| 	arqtext.clear(); | ||||
| 	txstring.clear(); | ||||
| 	pText = 0; | ||||
| 	arq_text_available = false; | ||||
| 	bSend0x06 = true; | ||||
| 	pthread_mutex_unlock (&arq_mutex); | ||||
| } | ||||
| 
 | ||||
| //======================================================================
 | ||||
| // Special notification for PSKMAIL: new mode marked only, in following
 | ||||
| // format: "<DC2><Mode:newmode>", with <DC2> = '0x12'.
 | ||||
| //======================================================================
 | ||||
| void pskmail_notify_rsid(trx_mode mode) | ||||
| { | ||||
| 	char buf[64]; | ||||
| 	static char buf[64]; | ||||
| 	memset(buf, 0, sizeof(buf)); | ||||
| 	int n = snprintf(buf, sizeof(buf), | ||||
| 				"\x12<Mode:%s>\n", | ||||
| 				mode_info[mode].name); | ||||
|  | @ -899,12 +917,15 @@ void pskmail_notify_rsid(trx_mode mode) | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| //======================================================================
 | ||||
| // Special notification for PSKMAIL: signal to noise measured by decoder
 | ||||
| // format "<DC2><s2n: CC, A.a, D.d>"
 | ||||
| // where CC = count, A.a = average s/n, D.d = Std dev of s/n
 | ||||
| //======================================================================
 | ||||
| void pskmail_notify_s2n(double s2n_ncount, double s2n_avg, double s2n_stddev) | ||||
| { | ||||
| 	char buf[64]; | ||||
| 	static char buf[64]; | ||||
| 	memset(buf, 0, sizeof(buf)); | ||||
| 	int n = snprintf(buf, sizeof(buf), | ||||
| 				"\x12<s2n: %1.0f, %1.1f, %1.1f>\n", | ||||
| 				s2n_ncount, s2n_avg, s2n_stddev); | ||||
|  |  | |||
|  | @ -52,6 +52,14 @@ | |||
| #include "icons.h" | ||||
| #include "gettext.h" | ||||
| 
 | ||||
| #include "threads.h" | ||||
| 
 | ||||
| #ifndef FLARQ_VERSION | ||||
| #	include "fl_digi.h" | ||||
| #endif | ||||
| 
 | ||||
| static pthread_mutex_t debug_mutex = PTHREAD_MUTEX_INITIALIZER; | ||||
| 
 | ||||
| extern Fl_Double_Window *fl_digi_main; | ||||
| extern void update_main_title(); | ||||
| 
 | ||||
|  | @ -76,6 +84,8 @@ debug* debug::inst = 0; | |||
| debug::level_e debug::level = debug::INFO_LEVEL; | ||||
| uint32_t debug::mask = ~0u; | ||||
| 
 | ||||
| bool debug_pskmail = false; | ||||
| 
 | ||||
| static const char* prefix[] = { | ||||
| 	_("Quiet"), _("Error"), _("Warning"), _("Info"), _("Verbose"), _("Debug") | ||||
| }; | ||||
|  | @ -154,6 +164,7 @@ void debug::start(const char* filename) | |||
| 
 | ||||
| void debug::stop(void) | ||||
| { | ||||
| 	guard_lock debug_lock(&debug_mutex); | ||||
| 	if (window) { | ||||
| 		window->hide(); | ||||
| 		delete window; | ||||
|  | @ -168,10 +179,11 @@ static char fmt[1024]; | |||
| 
 | ||||
| void debug::log(level_e level, const char* func, const char* srcf, int line, const char* format, ...) | ||||
| { | ||||
| 	guard_lock debug_lock(&debug_mutex); | ||||
| 
 | ||||
| 	if (!inst) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (unlikely(debug::level == DEBUG_LEVEL) || DEBUG_PSKMAIL) { | ||||
| 	if (unlikely(debug::level == DEBUG_LEVEL) || debug_pskmail) { | ||||
| 		time_t t = time(NULL); | ||||
| 		struct tm stm; | ||||
| 		(void)localtime_r(&t, &stm); | ||||
|  |  | |||
		Ładowanie…
	
		Reference in New Issue
	
	 David Freese
						David Freese