diff options
Diffstat (limited to 'vxi11_server.c')
-rw-r--r-- | vxi11_server.c | 400 |
1 files changed, 400 insertions, 0 deletions
diff --git a/vxi11_server.c b/vxi11_server.c new file mode 100644 index 0000000..4c3a837 --- /dev/null +++ b/vxi11_server.c @@ -0,0 +1,400 @@ +#include "vxi11.h" +#include "globals.h" +#include "gpib.h" +#include "parser.h" +#include <stdio.h> +#include <rpc/rpc.h> +#include <stdbool.h> +#include <sys/socket.h> +#include <netinet/in.h> + +#define DEBUG + +#ifdef DEBUG +#include <stdlib.h> +#endif + +#define SIZEOFARRAY(a) (sizeof(a) / sizeof(a[0])) + +#define ERR_SYNTAXERROR 1 +#define ERR_DEVICENOTACCESSIBLE 3 +#define ERR_INVALIDLINKINDENTIFIER 4 +#define ERR_PARAMETERERROR 5 +#define ERR_CHANNELNOTESTABLISHED 6 +#define ERR_OPERATIONNOTSUPPORTED 8 +#define ERR_OUTOFRESOURCES 9 +#define ERR_DEVICELOCKEDBYANOTHERLINK 11 +#define ERR_NOLOCKHELDBYTHISLINK 12 +#define ERR_IOTIMEOUT 15 +#define ERR_IOERROR 17 +#define ERR_INVALIDADDRESS 21 +#define ERR_ABORT 23 +#define ERR_CHANNELALREADYESTABLISHED 29 + +static CLIENT* intclient = NULL; + +typedef struct { +} ActiveLink; + +static ActiveLink* links[MAX_SESSIONS] = { NULL }; + +static bool isValidLink(int linkid) { + return links[linkid] != NULL; +} + +static bool isLocked() { + return globals.VxiLocks.locked_network_server != NO_SERVER_LOCKED; +} + +static bool haveLock(int lid) { + return globals.VxiLocks.locked_network_server == lid; +} + +#define FLAG_WAITLOCK 1 + +// todo +static bool waitForLock(Device_Flags flags, long timeout) { + if (!(flags & FLAG_WAITLOCK)) + return false; + return false; +} + +static void lock(int lid) { + globals.VxiLocks.locked_network_server = lid; +} + +static void unlock() { + globals.VxiLocks.locked_network_server = NO_SERVER_LOCKED; +} + +Device_Error * +device_abort_1_svc(Device_Link *argp, struct svc_req *rqstp) { + static Device_Error result; +#ifdef DEBUG + printf("device_abort_1_svc()\n"); +#endif + if (!isValidLink(*argp)) + result.error = ERR_INVALIDLINKINDENTIFIER; + else { + result.error = 0; + } + return &result; +} + +Create_LinkResp * +create_link_1_svc(Create_LinkParms *argp, struct svc_req *rqstp) { + static Create_LinkResp result; +#ifdef DEBUG + printf("create_link_1_svc()\n"); +#endif + if (globals.Remote.vxi_connections == MAX_SESSIONS) { + result.error = ERR_OUTOFRESOURCES; + } + else { + if (argp->lockDevice && isLocked() && !waitForLock(FLAG_WAITLOCK, argp->lock_timeout)) { + result.error = ERR_DEVICELOCKEDBYANOTHERLINK; + } + else { + ActiveLink* link = malloc(sizeof(ActiveLink)); + if (link == NULL) { + result.error = ERR_OUTOFRESOURCES; + } + else { + + int linkid; + for (linkid = 0; linkid < SIZEOFARRAY(links); linkid++) { + if (links[linkid] == NULL) { + links[linkid] = link; + break; + } + } + + struct sockaddr_in sin; + socklen_t len = sizeof(sin); + getsockname(rqstp->rq_xprt->xp_sock, (struct sockaddr *) &sin, &len); + result.error = 0; + result.abortPort = ntohs(sin.sin_port); + result.lid = linkid; + globals.Remote.vxi_connections++; + + } + } + } + return &result; +} + +Device_WriteResp * +device_write_1_svc(Device_WriteParms *argp, struct svc_req *rqstp) { + static Device_WriteResp result; +#ifdef DEBUG + printf("device_write_1_svc()\n"); +#endif + if (!isValidLink(argp->lid)) + result.error = ERR_INVALIDLINKINDENTIFIER; + else { + if (isLocked() && !haveLock(argp->lid) && !waitForLock(argp->flags, argp->lock_timeout)) + result.error = ERR_DEVICELOCKEDBYANOTHERLINK; + else { +#ifdef DEBUG + printf("got %s on link %d\n", argp->data.data_val, argp->lid); +#endif + Parser_main(argp->data, 0, GPIB_and_VXI_start_query_response, NULL); + result.size = argp->data.data_len; + result.error = 0; + } + } + return &result; +} + +Device_ReadResp * +device_read_1_svc(Device_ReadParms *argp, struct svc_req *rqstp) { + static Device_ReadResp result; +#ifdef DEBUG + printf("device_read_1_svc()\n"); +#endif + if (!isValidLink(argp->lid)) + result.error = ERR_INVALIDLINKINDENTIFIER; + else if (isLocked() && !haveLock(argp->lid) && !waitForLock(argp->flags, argp->lock_timeout)) + result.error = ERR_DEVICELOCKEDBYANOTHERLINK; + else { + result.data.data_val = "HELLO!"; + result.data.data_len = 7; + result.error = 0; + result.reason = 0x4; + } + return &result; +} + +Device_ReadStbResp * +device_readstb_1_svc(Device_GenericParms *argp, struct svc_req *rqstp) { + static Device_ReadStbResp result; +#ifdef DEBUG + printf("device_readstb_1_svc()\n"); +#endif + if (!isValidLink(argp->lid)) + result.error = ERR_INVALIDLINKINDENTIFIER; + else if (isLocked() && !haveLock(argp->lid) && !waitForLock(argp->flags, argp->lock_timeout)) + result.error = ERR_DEVICELOCKEDBYANOTHERLINK; + else { + result.error = 0; + result.stb = GPIB_and_VXI_get_STB(); + } + return &result; +} + +Device_Error * +device_trigger_1_svc(Device_GenericParms *argp, struct svc_req *rqstp) { + static Device_Error result; +#ifdef DEBUG + printf("device_trigger_1_svc()\n"); +#endif + if (!isValidLink(argp->lid)) + result.error = ERR_INVALIDLINKINDENTIFIER; + else if (isLocked() && !haveLock(argp->lid) && !waitForLock(argp->flags, argp->lock_timeout)) + result.error = ERR_DEVICELOCKEDBYANOTHERLINK; + else { + result.error = 0; + } + return &result; +} + +Device_Error * +device_clear_1_svc(Device_GenericParms *argp, struct svc_req *rqstp) { + static Device_Error result; +#ifdef DEBUG + printf("device_clear_1_svc()\n"); +#endif + if (!isValidLink(argp->lid)) + result.error = ERR_INVALIDLINKINDENTIFIER; + else if (isLocked() && !haveLock(argp->lid) && !waitForLock(argp->flags, argp->lock_timeout)) + result.error = ERR_DEVICELOCKEDBYANOTHERLINK; + else { + result.error = 0; + } + return &result; +} + +Device_Error * +device_remote_1_svc(Device_GenericParms *argp, struct svc_req *rqstp) { + static Device_Error result; +#ifdef DEBUG + printf("device_remote_1_svc()\n"); +#endif + if (!isValidLink(argp->lid)) + result.error = ERR_INVALIDLINKINDENTIFIER; + else if (isLocked() && !haveLock(argp->lid) && !waitForLock(argp->flags, argp->lock_timeout)) + result.error = ERR_DEVICELOCKEDBYANOTHERLINK; + else { + if (isLocked() && !haveLock(argp->lid)) + result.error = ERR_DEVICELOCKEDBYANOTHERLINK; + else + result.error = 0; + } + return &result; +} + +Device_Error * +device_local_1_svc(Device_GenericParms *argp, struct svc_req *rqstp) { + static Device_Error result; +#ifdef DEBUG + printf("device_local_1_svc()\n"); +#endif + if (!isValidLink(argp->lid)) + result.error = ERR_INVALIDLINKINDENTIFIER; + else if (isLocked() && !haveLock(argp->lid) && !waitForLock(argp->flags, argp->lock_timeout)) + result.error = ERR_DEVICELOCKEDBYANOTHERLINK; + else { + if (isLocked() && !haveLock(argp->lid)) + result.error = ERR_DEVICELOCKEDBYANOTHERLINK; + else + result.error = 0; + } + return &result; +} + +Device_Error * +device_lock_1_svc(Device_LockParms *argp, struct svc_req *rqstp) { + static Device_Error result; +#ifdef DEBUG + printf("device_lock_1_svc()\n"); +#endif + if (!isValidLink(argp->lid)) + result.error = ERR_INVALIDLINKINDENTIFIER; + else { + if (isLocked(argp->lid)) { + result.error = ERR_DEVICELOCKEDBYANOTHERLINK; + if (haveLock(argp->lid)) { + // maybe do something here to warn about a device trying to lock multiple times? + } + } + else { + lock(argp->lid); + result.error = 0; + } + } + return &result; +} + +Device_Error * +device_unlock_1_svc(Device_Link *argp, struct svc_req *rqstp) { + static Device_Error result; +#ifdef DEBUG + printf("device_unlock_1_svc()\n"); +#endif + if (!isValidLink(*argp)) + result.error = ERR_INVALIDLINKINDENTIFIER; + else { + if (!isLocked(*argp) || !haveLock(*argp)) + result.error = ERR_NOLOCKHELDBYTHISLINK; + else { + result.error = 0; + unlock(); + } + } + return &result; +} + +Device_Error * +device_enable_srq_1_svc(Device_EnableSrqParms *argp, struct svc_req *rqstp) { + static Device_Error result; +#ifdef DEBUG + printf("device_enable_srq_1_svc()\n"); +#endif + if (!isValidLink(argp->lid)) + result.error = ERR_INVALIDLINKINDENTIFIER; + else { + result.error = 0; + } + return &result; +} + +Device_DocmdResp * +device_docmd_1_svc(Device_DocmdParms *argp, struct svc_req *rqstp) { + static Device_DocmdResp result; +#ifdef DEBUG + printf("device_docmd_1_svc()\n"); +#endif + if (!isValidLink(argp->lid)) + result.error = ERR_INVALIDLINKINDENTIFIER; + else if (isLocked() && !haveLock(argp->lid) && !waitForLock(argp->flags, argp->lock_timeout)) + result.error = ERR_DEVICELOCKEDBYANOTHERLINK; + else { + result.data_out.data_out_len = 0; + result.data_out.data_out_val = NULL; + result.error = ERR_OPERATIONNOTSUPPORTED; + } + return &result; +} + +Device_Error * +destroy_link_1_svc(Device_Link *argp, struct svc_req *rqstp) { + static Device_Error result; +#ifdef DEBUG + printf("destroy_link_1_svc()\n"); +#endif + int lid = *argp; + if (!isValidLink(lid)) + result.error = ERR_INVALIDLINKINDENTIFIER; + else { +#ifdef DEBUG + printf("link %d destroyed\n", lid); +#endif + free(links[lid]); + links[lid] = NULL; + } + + globals.Remote.vxi_connections--; + return &result; +} + +Device_Error * +create_intr_chan_1_svc(Device_RemoteFunc *argp, struct svc_req *rqstp) { + static Device_Error result; +#ifdef DEBUG + printf("create_intr_chan_1_svc()\n"); + char clientaddressstring[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &argp->hostAddr, clientaddressstring, sizeof(clientaddressstring)); + printf("Client %s is asking for an interrupt connection on port %u\n", clientaddressstring, argp->hostPort); +#endif + if (argp->progFamily != DEVICE_TCP || argp->progNum != DEVICE_INTR || argp->progVers != DEVICE_INTR_VERSION) + result.error = ERR_OPERATIONNOTSUPPORTED; + else if (intclient != NULL) { + result.error = ERR_CHANNELALREADYESTABLISHED; + } + else { + struct sockaddr_in clientaddr; + clientaddr.sin_family = AF_INET; + clientaddr.sin_port = htons(argp->hostPort); + clientaddr.sin_addr.s_addr = argp->hostAddr; + int sock = RPC_ANYSOCK; + CLIENT* clnt = clnttcp_create(&clientaddr, DEVICE_INTR, DEVICE_INTR_VERSION, &sock, 0, 0); + if (clnt == NULL) { +#ifdef DEBUG + printf("Couldn't create interrupt channel client\n"); +#endif + result.error = ERR_CHANNELNOTESTABLISHED; + } + else { + intclient = clnt; + result.error = 0; + } + } + return &result; +} + +Device_Error * +destroy_intr_chan_1_svc(void *argp, struct svc_req *rqstp) { + static Device_Error result; +#ifdef DEBUG + printf("destroy_intr_chan_1_svc()\n"); +#endif + if (intclient == NULL) { + result.error = ERR_CHANNELNOTESTABLISHED; + } + else { + intclient = NULL; + result.error = 0; + } + return &result; +} + |