kopia lustrzana https://github.com/Hamlib/Hamlib
rodzic
35c5964f81
commit
3d780676b5
|
@ -106,6 +106,13 @@
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__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
|
//! @cond Doxygen_Suppress
|
||||||
extern HAMLIB_EXPORT_VAR(const char) hamlib_version[];
|
extern HAMLIB_EXPORT_VAR(const char) hamlib_version[];
|
||||||
extern HAMLIB_EXPORT_VAR(const char) hamlib_copyright[];
|
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;
|
typedef unsigned long rig_useconds_t;
|
||||||
extern HAMLIB_EXPORT(int) hl_usleep(rig_useconds_t msec);
|
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
|
//! @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_GET must have cookie=NULL or NULL returned
|
||||||
* RIG_COOKIE_RENEW 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;
|
* 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
|
// only 1 client can have the cookie so these can be static
|
||||||
double time_curr, time_last_used = 0;
|
// 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;
|
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)
|
switch (cookie_cmd)
|
||||||
{
|
{
|
||||||
case RIG_COOKIE_RELEASE:
|
case RIG_COOKIE_RELEASE:
|
||||||
if (cookie == NULL) {
|
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)
|
|
||||||
{
|
{
|
||||||
cookie_save[0] = 0;
|
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): coookie NULL so nothing to do\n",
|
||||||
return NULL;
|
__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;
|
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
|
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d) %s renew request granted\n", __FILE__,
|
||||||
// if we already have a cookie and somebody asks see if we should expire the old one
|
__LINE__, cookie);
|
||||||
printf("%d cookie_cmd=%d\n", (int)strlen(cookie_save), cookie_cmd);
|
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);
|
clock_gettime(CLOCK_REALTIME, &tp);
|
||||||
time_curr = tp.tv_sec + tp.tv_nsec / 1e9;
|
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");
|
printf("Cookie %s in use\n", cookie_save);
|
||||||
rig_debug(RIG_DEBUG_ERR, "%s(%d): cookie==NULL but not RIG_COOKIE_GET\n",
|
rig_debug(RIG_DEBUG_ERR, "%s(%d): %s cookie is in use\n", __FILE__, __LINE__,
|
||||||
__FILE__, __LINE__);
|
cookie_save);
|
||||||
return NULL;
|
return -RIG_BUSBUSY;
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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));
|
date_strget(cookie_save, sizeof(cookie_save));
|
||||||
clock_gettime(CLOCK_REALTIME, &tp);
|
// add on our random number to ensure uniqueness
|
||||||
time_curr = time_last_used = tp.tv_sec + tp.tv_nsec / 1e9;
|
snprintf(cookie, cookie_len, "%s %ld\n", cookie_save, random());
|
||||||
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): cookie %s granted, time_curr=%f\n",
|
strcpy(cookie_save, cookie);
|
||||||
__FILE__, __LINE__, cookie_save, time_curr);
|
time_last_used = time_curr;
|
||||||
return cookie_save;
|
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): %s new cookie request granted\n",
|
||||||
}
|
__FILE__, __LINE__, cookie_save);
|
||||||
else if (strlen(cookie_save) == 0) // NULL should only be for GET
|
return RIG_OK;
|
||||||
{
|
break;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rig_debug(RIG_DEBUG_ERR, "%s(%d): unknown condition!!\n'", __FILE__, __LINE__);
|
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
|
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
|
RIGCOMMONSRC = rigctl_parse.c rigctl_parse.h dumpcaps.c uthash.h
|
||||||
ROTCOMMONSRC = rotctl_parse.c rotctl_parse.h dumpcaps_rot.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
|
EXTRA_DIST = rigmatrix_head.html rig_split_lst.awk testctld.pl testrotctld.pl
|
||||||
|
|
||||||
# Support 'make check' target for simple tests
|
# 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)
|
TESTS = $(check_SCRIPTS)
|
||||||
|
|
||||||
|
@ -105,4 +105,8 @@ testcache.sh:
|
||||||
echo './testcache 1' > testcache.sh
|
echo './testcache 1' > testcache.sh
|
||||||
chmod +x ./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