00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00036
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;
00093 else
00094 return -1;
00095 } else if (nread == 0)
00096 break;
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;
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
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
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
00219 if (vmdsock_selread(s, 5) != 1) return -1;
00220
00221
00222 type = imd_recv_header_nolengthswap(s, &buf);
00223 if (type != IMD_HANDSHAKE) return -1;
00224
00225
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
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