00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
00041
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;
00098 else
00099 return -1;
00100 } else if (nread == 0)
00101 break;
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;
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
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
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
00224 if (vmdsock_selread(s, 5) != 1) return -1;
00225
00226
00227 type = imd_recv_header_nolengthswap(s, &buf);
00228 if (type != IMD_HANDSHAKE) return -1;
00229
00230
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
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