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

imd.C

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

Generated on Fri Aug 29 01:27:01 2008 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002