summaryrefslogtreecommitdiff
path: root/vxi11_server.c
diff options
context:
space:
mode:
Diffstat (limited to 'vxi11_server.c')
-rw-r--r--vxi11_server.c400
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;
+}
+