kopia lustrzana https://github.com/Hamlib/Hamlib
rodzic
35c5964f81
commit
3d780676b5
|
@ -106,6 +106,13 @@
|
|||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* \brief size of cookie request buffer
|
||||
* Minimum size of cookie buffer to pass to rig_cookie
|
||||
*/
|
||||
// cookie is 26-char time code plus 10-char (2^31-1) random number
|
||||
#define HAMLIB_COOKIE_SIZE 37
|
||||
|
||||
//! @cond Doxygen_Suppress
|
||||
extern HAMLIB_EXPORT_VAR(const char) hamlib_version[];
|
||||
extern HAMLIB_EXPORT_VAR(const char) hamlib_copyright[];
|
||||
|
@ -3047,7 +3054,7 @@ extern HAMLIB_EXPORT(int) rig_get_cache(RIG *rig, vfo_t vfo, freq_t *freq, int *
|
|||
typedef unsigned long rig_useconds_t;
|
||||
extern HAMLIB_EXPORT(int) hl_usleep(rig_useconds_t msec);
|
||||
|
||||
extern HAMLIB_EXPORT(char *) rig_cookie(char *cookie, enum cookie_e cookie_cmd);
|
||||
extern HAMLIB_EXPORT(int) rig_cookie(RIG *rig, enum cookie_e cookie_cmd, char *cookie, int cookie_len);
|
||||
|
||||
//! @endcond
|
||||
|
||||
|
|
142
src/rig.c
142
src/rig.c
|
@ -6473,82 +6473,116 @@ const char *HAMLIB_API rig_copyright()
|
|||
* RIG_COOKIE_GET must have cookie=NULL or NULL returned
|
||||
* RIG_COOKIE_RENEW must have cookie!=NULL or NULL returned
|
||||
* RIG_COOKIE_RELEASE must have cookie!=NULL or NULL returned;
|
||||
* Cookies should only be used when needed to keep commands sequenced correctly
|
||||
* For example, when setting both VFOA and VFOB frequency and mode
|
||||
* Example to wait for cookie, do rig commands, and release
|
||||
* while((cookie=rig_cookie(NULL, RIG_COOKIE_GET)) == NULL) hl_usleep(10*1000);
|
||||
* set_freq A;set mode A;set freq B;set modeB;
|
||||
* rig_cookie(cookie,RIG_COOKIE_RELEASE);
|
||||
*/
|
||||
char *rig_cookie(char *cookie, enum cookie_e cookie_cmd)
|
||||
int HAMLIB_API rig_cookie(RIG *rig, enum cookie_e cookie_cmd, char *cookie,
|
||||
int cookie_len)
|
||||
{
|
||||
static char cookie_save[32]; // only one client can have the cookie
|
||||
double time_curr, time_last_used = 0;
|
||||
// only 1 client can have the cookie so these can be static
|
||||
// this should also prevent problems with DLLs & shared libraies
|
||||
// the debug_msg is another non-thread-safe which this will help fix
|
||||
// 27 char cookie will last until the year 10000
|
||||
static char cookie_save[HAMLIB_COOKIE_SIZE]; // only one client can have the 26-char cookie
|
||||
static double time_last_used;
|
||||
double time_curr;
|
||||
struct timespec tp;
|
||||
|
||||
if (cookie_len < 27)
|
||||
{
|
||||
rig_debug(RIG_DEBUG_ERR, "%s(%d): cookie_len < 32 so returning NULL!!\n",
|
||||
__FILE__, __LINE__);
|
||||
return -RIG_EINTERNAL;
|
||||
}
|
||||
|
||||
switch (cookie_cmd)
|
||||
{
|
||||
case RIG_COOKIE_RELEASE:
|
||||
if (cookie == NULL) {
|
||||
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): coookie NULL so nothing to do\n", __FILE__, __LINE__);
|
||||
return NULL; // nothing to do
|
||||
}
|
||||
if (strcmp(cookie,cookie_save)==0)
|
||||
if (cookie == NULL)
|
||||
{
|
||||
cookie_save[0] = 0;
|
||||
return NULL;
|
||||
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): coookie NULL so nothing to do\n",
|
||||
__FILE__, __LINE__);
|
||||
return -RIG_EINVAL; // nothing to do
|
||||
}
|
||||
|
||||
if (strcmp(cookie, cookie_save) == 0) // matching cookie so we'll clear it
|
||||
{
|
||||
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): %s coookie released\n",
|
||||
__FILE__, __LINE__, cookie_save);
|
||||
memset(cookie_save, 0, sizeof(cookie_save));
|
||||
return RIG_OK;
|
||||
}
|
||||
else // not the right cookie!!
|
||||
{
|
||||
rig_debug(RIG_DEBUG_ERR,
|
||||
"%s(%d): %s can't release cookie as cookie %s is active\n", __FILE__, __LINE__,
|
||||
cookie, cookie_save);
|
||||
return -RIG_BUSBUSY;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
if (cookie == NULL && cookie_cmd == RIG_COOKIE_GET)
|
||||
|
||||
case RIG_COOKIE_RENEW:
|
||||
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): %s comparing renew request to %s==%d\n",
|
||||
__FILE__, __LINE__, cookie, cookie_save, strcmp(cookie, cookie_save));
|
||||
|
||||
if (strcmp(cookie, cookie_save) == 0) // matching cookie so we'll renew it
|
||||
{
|
||||
// asking for a cookie but somebody may already have it
|
||||
// if we already have a cookie and somebody asks see if we should expire the old one
|
||||
printf("%d cookie_cmd=%d\n", (int)strlen(cookie_save), cookie_cmd);
|
||||
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d) %s renew request granted\n", __FILE__,
|
||||
__LINE__, cookie);
|
||||
clock_gettime(CLOCK_REALTIME, &tp);
|
||||
time_last_used = tp.tv_sec + tp.tv_nsec / 1e9;
|
||||
return RIG_OK;
|
||||
}
|
||||
|
||||
rig_debug(RIG_DEBUG_ERR,
|
||||
"%s(%d): %s renew request refused %s is active\n",
|
||||
__FILE__, __LINE__, cookie, cookie_save);
|
||||
return -RIG_EINVAL; // wrong cookie
|
||||
|
||||
break;
|
||||
|
||||
case RIG_COOKIE_GET:
|
||||
// the way we expire cookies is if somebody else asks for one and the last renewal is > 1 second ago
|
||||
// a polite client will have released the cookie
|
||||
// we are just allow for a crashed client that fails to release:q
|
||||
clock_gettime(CLOCK_REALTIME, &tp);
|
||||
time_curr = tp.tv_sec + tp.tv_nsec / 1e9;
|
||||
rig_debug(RIG_DEBUG_ERR, "%s(%d): time_curr=%f\n", __FILE__, __LINE__,
|
||||
time_curr);
|
||||
|
||||
if (time_curr - time_last_used < 1)
|
||||
if ((strcmp(cookie_save, cookie) == 0)
|
||||
&& (time_curr - time_last_used < 1)) // then we will deny the request
|
||||
{
|
||||
printf("Cookie in use\n");
|
||||
rig_debug(RIG_DEBUG_ERR, "%s(%d): cookie==NULL but not RIG_COOKIE_GET\n",
|
||||
__FILE__, __LINE__);
|
||||
return NULL;
|
||||
}
|
||||
else if (strlen(cookie_save)!=0)
|
||||
{
|
||||
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): cookie expired so we will grant\n", __FILE__, __LINE__);
|
||||
cookie_save[0] = 0;
|
||||
}
|
||||
printf("Cookie %s in use\n", cookie_save);
|
||||
rig_debug(RIG_DEBUG_ERR, "%s(%d): %s cookie is in use\n", __FILE__, __LINE__,
|
||||
cookie_save);
|
||||
return -RIG_BUSBUSY;
|
||||
}
|
||||
|
||||
if (strlen(cookie_save) == 0 && cookie_cmd == RIG_COOKIE_GET)
|
||||
if (cookie_save[0] != 0)
|
||||
{
|
||||
rig_debug(RIG_DEBUG_ERR,
|
||||
"%s(%d): %s cookie has expired after %.3f seconds....overriding with new cookie\n",
|
||||
__FILE__, __LINE__, cookie_save, time_curr - time_last_used);
|
||||
}
|
||||
|
||||
date_strget(cookie_save, sizeof(cookie_save));
|
||||
clock_gettime(CLOCK_REALTIME, &tp);
|
||||
time_curr = time_last_used = tp.tv_sec + tp.tv_nsec / 1e9;
|
||||
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): cookie %s granted, time_curr=%f\n",
|
||||
__FILE__, __LINE__, cookie_save, time_curr);
|
||||
return cookie_save;
|
||||
}
|
||||
else if (strlen(cookie_save) == 0) // NULL should only be for GET
|
||||
{
|
||||
rig_debug(RIG_DEBUG_ERR, "%s(%d): cookie==NULL but not RIG_COOKIE_GET\n",
|
||||
__FILE__, __LINE__);
|
||||
return NULL;
|
||||
}
|
||||
else if (cookie_cmd == RIG_COOKIE_RENEW)
|
||||
{
|
||||
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): cookie %s renewed time_curr=%g\n",
|
||||
__FILE__, __LINE__,
|
||||
cookie, time_curr);
|
||||
return cookie;
|
||||
}
|
||||
else if (cookie_cmd == RIG_COOKIE_RELEASE)
|
||||
{
|
||||
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): cookie %s released\n", __FILE__, __LINE__,
|
||||
cookie);
|
||||
cookie_save[0] = 0;
|
||||
// add on our random number to ensure uniqueness
|
||||
snprintf(cookie, cookie_len, "%s %ld\n", cookie_save, random());
|
||||
strcpy(cookie_save, cookie);
|
||||
time_last_used = time_curr;
|
||||
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): %s new cookie request granted\n",
|
||||
__FILE__, __LINE__, cookie_save);
|
||||
return RIG_OK;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
rig_debug(RIG_DEBUG_ERR, "%s(%d): unknown condition!!\n'", __FILE__, __LINE__);
|
||||
return NULL;
|
||||
return -RIG_EPROTO;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ DISTCLEANFILES = rigctl.log rigctl.sum testbcd.log testbcd.sum
|
|||
|
||||
bin_PROGRAMS = rigctl rigctld rigmem rigsmtr rigswr rotctl rotctld rigctlcom ampctl ampctld
|
||||
|
||||
check_PROGRAMS = dumpmem testrig testrigopen testrigcaps testtrn testbcd testfreq listrigs testloc rig_bench testcache cachetest cachetest2
|
||||
check_PROGRAMS = dumpmem testrig testrigopen testrigcaps testtrn testbcd testfreq listrigs testloc rig_bench testcache cachetest cachetest2 testcookie
|
||||
|
||||
RIGCOMMONSRC = rigctl_parse.c rigctl_parse.h dumpcaps.c uthash.h
|
||||
ROTCOMMONSRC = rotctl_parse.c rotctl_parse.h dumpcaps_rot.c uthash.h
|
||||
|
@ -76,7 +76,7 @@ endif
|
|||
EXTRA_DIST = rigmatrix_head.html rig_split_lst.awk testctld.pl testrotctld.pl
|
||||
|
||||
# Support 'make check' target for simple tests
|
||||
check_SCRIPTS = testrig.sh testfreq.sh testbcd.sh testloc.sh testrigcaps.sh testcache.sh
|
||||
check_SCRIPTS = testrig.sh testfreq.sh testbcd.sh testloc.sh testrigcaps.sh testcache.sh testcookie.sh
|
||||
|
||||
TESTS = $(check_SCRIPTS)
|
||||
|
||||
|
@ -105,4 +105,8 @@ testcache.sh:
|
|||
echo './testcache 1' > testcache.sh
|
||||
chmod +x ./testcache.sh
|
||||
|
||||
CLEANFILES = testrig.sh testfreq.sh testbcd.sh testloc.sh testrigcaps.sh testcache.sh
|
||||
testcookie.sh:
|
||||
echo './testcookie 1' > testcookie.sh
|
||||
chmod +x ./testcookie.sh
|
||||
|
||||
CLEANFILES = testrig.sh testfreq.sh testbcd.sh testloc.sh testrigcaps.sh testcache.sh testcookie.sh
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
#include <hamlib/rig.h>
|
||||
|
||||
// GET tests
|
||||
int test1()
|
||||
{
|
||||
int retcode;
|
||||
// Normal get
|
||||
char cookie[HAMLIB_COOKIE_SIZE];
|
||||
retcode = rig_cookie(NULL, RIG_COOKIE_GET, cookie, sizeof(cookie));
|
||||
|
||||
if (retcode == RIG_OK) { printf("Test#1a OK\n"); }
|
||||
else {printf("Test#1a Failed\n"); return 1;}
|
||||
|
||||
// Should be able to release and get it right back
|
||||
rig_cookie(NULL, RIG_COOKIE_RELEASE, cookie, sizeof(cookie));
|
||||
retcode = rig_cookie(NULL, RIG_COOKIE_GET, cookie, sizeof(cookie));
|
||||
|
||||
if (retcode == RIG_OK) { printf("Test#1b OK\n"); }
|
||||
else {printf("Test#1b Failed\n"); return 1;}
|
||||
|
||||
|
||||
// Doing a get when another cookie is active should fail
|
||||
char cookie2[HAMLIB_COOKIE_SIZE];
|
||||
cookie2[0] = 0;
|
||||
retcode = rig_cookie(NULL, RIG_COOKIE_GET, cookie2, sizeof(cookie2));
|
||||
|
||||
if (retcode == RIG_OK) { printf("Test#1c OK\n"); }
|
||||
else {printf("Test#1c Failed\n"); return 1;}
|
||||
|
||||
// after 1 second we should be able to get a coookie
|
||||
// this means the cookie holder did not renew within 1 second
|
||||
hl_usleep(1500 * 1000); // after 1 second we should be able to get a coookie
|
||||
|
||||
retcode = rig_cookie(NULL, RIG_COOKIE_GET, cookie2, sizeof(cookie2));
|
||||
|
||||
if (retcode == RIG_OK) { printf("Test#1d OK\n"); }
|
||||
else {printf("Test#1d Failed\n"); return 1;}
|
||||
|
||||
retcode = rig_cookie(NULL, RIG_COOKIE_RELEASE, cookie2, sizeof(cookie2));
|
||||
|
||||
if (retcode == RIG_OK) { printf("Test#1e OK\n"); }
|
||||
else {printf("Test#1e Failed\n"); return 1;}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// RENEW tests
|
||||
int test2()
|
||||
{
|
||||
int retcode;
|
||||
char cookie[HAMLIB_COOKIE_SIZE];
|
||||
retcode = rig_cookie(NULL, RIG_COOKIE_GET, cookie, sizeof(cookie));
|
||||
|
||||
if (retcode == RIG_OK) { printf("Test#2a OK %s\n", cookie); }
|
||||
else {printf("Test#2a Failed\n"); return 1;}
|
||||
|
||||
retcode = rig_cookie(NULL, RIG_COOKIE_RELEASE, cookie, sizeof(cookie));
|
||||
|
||||
if (retcode == RIG_OK) { printf("Test#2b OK\n"); }
|
||||
else {printf("Test#2b Failed\n"); return 1;}
|
||||
|
||||
// get another cookie should work
|
||||
char cookie2[HAMLIB_COOKIE_SIZE];
|
||||
retcode = rig_cookie(NULL, RIG_COOKIE_GET, cookie2, sizeof(cookie2));
|
||||
|
||||
if (retcode == RIG_OK) { printf("Test#2c OK %s\n", cookie2); }
|
||||
else {printf("Test#2c Failed\n"); return 1;}
|
||||
|
||||
// should not be able to renew 1st cookie
|
||||
retcode = rig_cookie(NULL, RIG_COOKIE_RENEW, cookie, sizeof(cookie));
|
||||
|
||||
if (retcode != RIG_OK) { printf("Test#2d OK\n"); }
|
||||
else {printf("Test#2d Failed cookie=%s\n", cookie); return 1;}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
rig_set_debug(RIG_DEBUG_VERBOSE);
|
||||
|
||||
if (test1()) { return 1; }
|
||||
|
||||
if (test2()) { return 1; }
|
||||
|
||||
return 0;
|
||||
}
|
Ładowanie…
Reference in New Issue