Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

imd.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr
00003  *cr            (C) Copyright 1995-2019 The Board of Trustees of the
00004  *cr                        University of Illinois
00005  *cr                         All Rights Reserved
00006  *cr
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  * RCS INFORMATION:
00011  *
00012  *      $RCSfile: imd.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.20 $       $Date: 2019/01/17 21:21:03 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *  Lowest level interactive MD communication routines.
00019  *
00020  * LICENSE:
00021  *   UIUC Open Source License
00022  *   http://www.ks.uiuc.edu/Research/vmd/plugins/pluginlicense.html
00023  *
00024  ***************************************************************************/
00025 #include "imd.h"
00026 #include "vmdsock.h"
00027 #include <string.h>
00028 #include <errno.h>
00029 #include <stdlib.h>
00030 
00032 typedef struct {
00033   int32 type;
00034   int32 length;
00035 } IMDheader;
00036 
00037 #define HEADERSIZE 8
00038 #define IMDVERSION 2
00039 
00040 /* Only works with aligned 4-byte quantities, will cause a bus error */
00041 /* on some platforms if used on unaligned data.                      */
00042 void swap4_aligned(void *v, long ndata) {
00043   int *data = (int *) v;
00044   long i;
00045   int *N;
00046   for (i=0; i<ndata; i++) {
00047     N = data + i;
00048     *N=(((*N>>24)&0xff) | ((*N&0xff)<<24) |
00049         ((*N>>8)&0xff00) | ((*N&0xff00)<<8));
00050   }
00051 }
00052 
00053 static int32 imd_htonl(int32 h) {
00054   int32 n;
00055   ((char *)&n)[0] = (h >> 24) & 0x0FF;
00056   ((char *)&n)[1] = (h >> 16) & 0x0FF;
00057   ((char *)&n)[2] = (h >> 8) & 0x0FF;
00058   ((char *)&n)[3] = h & 0x0FF;
00059   return n;
00060 }
00061 
00063 typedef struct {
00064   unsigned int highest : 8;
00065   unsigned int high    : 8;
00066   unsigned int low     : 8;
00067   unsigned int lowest  : 8;
00068 } netint;
00069 
00070 static int32 imd_ntohl(int32 n) {
00071   int32 h = 0;
00072   netint net;
00073 
00074   memcpy((void *)&net,(void *)&n, sizeof(n));
00075   h |= net.highest << 24 | net.high << 16 | net.low << 8 | net.lowest;
00076   return h;
00077 }
00078 
00079 static void fill_header(IMDheader *header, IMDType type, int32 length) {
00080   header->type = imd_htonl((int32)type);
00081   header->length = imd_htonl(length);
00082 }
00083 
00084 static void swap_header(IMDheader *header) {
00085   header->type = imd_ntohl(header->type);
00086   header->length= imd_ntohl(header->length);
00087 }
00088 
00089 static int32 imd_readn(void *s, char *ptr, int32 n) {
00090   int32 nleft;
00091   int32 nread;
00092  
00093   nleft = n;
00094   while (nleft > 0) {
00095     if ((nread = vmdsock_read(s, ptr, nleft)) < 0) {
00096       if (errno == EINTR)
00097         nread = 0;         /* and call read() again */
00098       else
00099         return -1;
00100     } else if (nread == 0)
00101       break;               /* EOF */
00102     nleft -= nread;
00103     ptr += nread;
00104   }
00105   return n-nleft;
00106 }
00107 
00108 static int32 imd_writen(void *s, const char *ptr, int32 n) {
00109   int32 nleft;
00110   int32 nwritten;
00111 
00112   nleft = n;
00113   while (nleft > 0) {
00114     if ((nwritten = vmdsock_write(s, ptr, nleft)) <= 0) {
00115       if (errno == EINTR)
00116         nwritten = 0;
00117       else
00118         return -1;
00119     }
00120     nleft -= nwritten;
00121     ptr += nwritten;
00122   }
00123   return n;
00124 }
00125  
00126 
00127 int imd_disconnect(void *s) {
00128   IMDheader header;
00129   fill_header(&header, IMD_DISCONNECT, 0);
00130   return (imd_writen(s, (char *)&header, HEADERSIZE) != HEADERSIZE);
00131 }
00132 
00133 int imd_pause(void *s) {
00134   IMDheader header;
00135   fill_header(&header, IMD_PAUSE, 0);
00136   return (imd_writen(s, (char *)&header, HEADERSIZE) != HEADERSIZE);
00137 }
00138 
00139 int imd_kill(void *s) {
00140   IMDheader header;
00141   fill_header(&header, IMD_KILL, 0);
00142   return (imd_writen(s, (char *)&header, HEADERSIZE) != HEADERSIZE);
00143 }
00144 
00145 static int imd_go(void *s) {
00146   IMDheader header;
00147   fill_header(&header, IMD_GO, 0);
00148   return (imd_writen(s, (char *)&header, HEADERSIZE) != HEADERSIZE);
00149 }
00150 
00151 
00152 int imd_handshake(void *s) {
00153   IMDheader header;
00154   fill_header(&header, IMD_HANDSHAKE, 1);
00155   header.length = IMDVERSION;   /* Not byteswapped! */
00156   return (imd_writen(s, (char *)&header, HEADERSIZE) != HEADERSIZE);
00157 }
00158 
00159 int imd_trate(void *s, int32 rate) {
00160   IMDheader header;
00161   fill_header(&header, IMD_TRATE, rate);
00162   return (imd_writen(s, (char *)&header, HEADERSIZE) != HEADERSIZE);
00163 }
00164 
00165 /* Data methods */
00166 int imd_send_mdcomm(void *s,int32 n,const int32 *indices,const float *forces) {
00167   int rc;
00168   int32 size = HEADERSIZE+16L*n;
00169   char *buf = (char *) malloc(sizeof(char) * size); 
00170   fill_header((IMDheader *)buf, IMD_MDCOMM, n);
00171   memcpy(buf+HEADERSIZE, indices, 4L*n);
00172   memcpy(buf+HEADERSIZE+4*n, forces, 12L*n);
00173   rc = (imd_writen(s, buf, size) != size);
00174   free(buf);
00175   return rc;
00176 }
00177 
00178 int imd_send_energies(void *s, const IMDEnergies *energies) {
00179   int rc;
00180   int32 size = HEADERSIZE+sizeof(IMDEnergies);
00181   char *buf = (char *) malloc(sizeof(char) * size);
00182   fill_header((IMDheader *)buf, IMD_ENERGIES, 1);
00183   memcpy(buf+HEADERSIZE, energies, sizeof(IMDEnergies));
00184   rc = (imd_writen(s, buf, size) != size);
00185   free(buf);
00186   return rc;
00187 }
00188 
00189 int imd_send_fcoords(void *s, int32 n, const float *coords) {
00190   int rc;
00191   int32 size = HEADERSIZE+12L*n;
00192   char *buf = (char *) malloc(sizeof(char) * size); 
00193   fill_header((IMDheader *)buf, IMD_FCOORDS, n);
00194   memcpy(buf+HEADERSIZE, coords, 12L*n);
00195   rc = (imd_writen(s, buf, size) != size);
00196   free(buf);
00197   return rc;
00198 }
00199 
00200 /* The IMD receive functions */
00201 IMDType imd_recv_header_nolengthswap(void *s, int32 *length) {
00202   IMDheader header;
00203   if (imd_readn(s, (char *)&header, HEADERSIZE) != HEADERSIZE)
00204     return IMD_IOERROR;
00205   *length = header.length;
00206   swap_header(&header);
00207   return (IMDType) header.type; 
00208 }
00209 
00210 IMDType imd_recv_header(void *s, int32 *length) {
00211   IMDheader header;
00212   if (imd_readn(s, (char *)&header, HEADERSIZE) != HEADERSIZE)
00213     return IMD_IOERROR;
00214   swap_header(&header);
00215   *length = header.length;
00216   return (IMDType) header.type; 
00217 }
00218 
00219 int imd_recv_handshake(void *s) {
00220   int32 buf;
00221   IMDType type;
00222 
00223   /* Wait up to 5 seconds for the handshake to come */
00224   if (vmdsock_selread(s, 5) != 1) return -1;
00225 
00226   /* Check to see that a valid handshake was received */
00227   type = imd_recv_header_nolengthswap(s, &buf);
00228   if (type != IMD_HANDSHAKE) return -1;
00229 
00230   /* Check its endianness, as well as the IMD version. */
00231   if (buf == IMDVERSION) {
00232     if (!imd_go(s)) return 0;
00233     return -1;
00234   }
00235 
00236   swap4_aligned(&buf, 1);
00237   if (buf == IMDVERSION) {
00238     if (!imd_go(s)) return 1;
00239   }
00240   
00241   /* We failed to determine endianness. */
00242   return -1; 
00243 }
00244 
00245 int imd_recv_mdcomm(void *s, int32 n, int32 *indices, float *forces) {
00246   if (imd_readn(s, (char *)indices, 4L*n) != 4L*n) return 1;
00247   if (imd_readn(s, (char *)forces, 12L*n) != 12L*n) return 1;
00248   return 0;
00249 }
00250 
00251 int imd_recv_energies(void *s, IMDEnergies *energies) {
00252   return (imd_readn(s, (char *)energies, sizeof(IMDEnergies))
00253           != sizeof(IMDEnergies));
00254 }
00255 
00256 int imd_recv_fcoords(void *s, int32 n, float *coords) {
00257   return (imd_readn(s, (char *)coords, 12L*n) != 12L*n);
00258 }
00259 

Generated on Thu Mar 28 02:43:19 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002