00001
00002
00003 #include "imd.h"
00004 #include "vmdsock.h"
00005 #include <string.h>
00006 #include <errno.h>
00007 #include <stdlib.h>
00008
00009 typedef struct {
00010 int32 type;
00011 int32 length;
00012 } IMDheader;
00013
00014 #define HEADERSIZE 8
00015 #define IMDVERSION 2
00016
00017 static void swap4(char *data, int ndata) {
00018 int i;
00019 char *dataptr;
00020 char b0, b1;
00021
00022 dataptr = data;
00023 for (i=0; i<ndata; i+=4) {
00024 b0 = dataptr[0];
00025 b1 = dataptr[1];
00026 dataptr[0] = dataptr[3];
00027 dataptr[1] = dataptr[2];
00028 dataptr[2] = b1;
00029 dataptr[3] = b0;
00030 dataptr += 4;
00031 }
00032 }
00033
00035 typedef union {
00036 int32 i;
00037 struct {
00038 unsigned int highest : 8;
00039 unsigned int high : 8;
00040 unsigned int low : 8;
00041 unsigned int lowest : 8;
00042 } b;
00043 } netint;
00044
00045 static int32 imd_htonl(int32 h) {
00046 netint n;
00047 n.b.highest = h >> 24;
00048 n.b.high = h >> 16;
00049 n.b.low = h >> 8;
00050 n.b.lowest = h;
00051 return n.i;
00052 }
00053
00054 static int32 imd_ntohl(int32 n) {
00055 netint u;
00056 u.i = n;
00057 return (u.b.highest << 24 | u.b.high << 16 | u.b.low << 8 | u.b.lowest);
00058 }
00059
00060 static void fill_header(IMDheader *header, IMDType type, int32 length) {
00061 header->type = imd_htonl((int32)type);
00062 header->length = imd_htonl(length);
00063 }
00064
00065 static void swap_header(IMDheader *header) {
00066 header->type = imd_ntohl(header->type);
00067 header->length= imd_ntohl(header->length);
00068 }
00069
00070 static int32 imd_readn(void *s, char *ptr, int32 n) {
00071 int32 nleft;
00072 int32 nread;
00073
00074 nleft = n;
00075 while (nleft > 0) {
00076 if ((nread = vmdsock_read(s, ptr, nleft)) < 0) {
00077 if (errno == EINTR)
00078 nread = 0;
00079 else
00080 return -1;
00081 } else if (nread == 0)
00082 break;
00083 nleft -= nread;
00084 ptr += nread;
00085 }
00086 return n-nleft;
00087 }
00088
00089 static int32 imd_writen(void *s, const char *ptr, int32 n) {
00090 int32 nleft;
00091 int32 nwritten;
00092
00093 nleft = n;
00094 while (nleft > 0) {
00095 if ((nwritten = vmdsock_write(s, ptr, nleft)) <= 0) {
00096 if (errno == EINTR)
00097 nwritten = 0;
00098 else
00099 return -1;
00100 }
00101 nleft -= nwritten;
00102 ptr += nwritten;
00103 }
00104 return n;
00105 }
00106
00107
00108 int imd_disconnect(void *s) {
00109 IMDheader header;
00110 fill_header(&header, IMD_DISCONNECT, 0);
00111 return (imd_writen(s, (char *)&header, HEADERSIZE) != HEADERSIZE);
00112 }
00113
00114 int imd_pause(void *s) {
00115 IMDheader header;
00116 fill_header(&header, IMD_PAUSE, 0);
00117 return (imd_writen(s, (char *)&header, HEADERSIZE) != HEADERSIZE);
00118 }
00119
00120 int imd_kill(void *s) {
00121 IMDheader header;
00122 fill_header(&header, IMD_KILL, 0);
00123 return (imd_writen(s, (char *)&header, HEADERSIZE) != HEADERSIZE);
00124 }
00125
00126 static int imd_go(void *s) {
00127 IMDheader header;
00128 fill_header(&header, IMD_GO, 0);
00129 return (imd_writen(s, (char *)&header, HEADERSIZE) != HEADERSIZE);
00130 }
00131
00132
00133 int imd_handshake(void *s) {
00134 IMDheader header;
00135 fill_header(&header, IMD_HANDSHAKE, 1);
00136 header.length = IMDVERSION;
00137 return (imd_writen(s, (char *)&header, HEADERSIZE) != HEADERSIZE);
00138 }
00139
00140 int imd_trate(void *s, int32 rate) {
00141 IMDheader header;
00142 fill_header(&header, IMD_TRATE, rate);
00143 return (imd_writen(s, (char *)&header, HEADERSIZE) != HEADERSIZE);
00144 }
00145
00146
00147
00148 int imd_send_mdcomm(void *s,int32 n,const int32 *indices,const float *forces) {
00149 int32 size = HEADERSIZE+16*n;
00150 char *buf = new char[size];
00151 fill_header((IMDheader *)buf, IMD_MDCOMM, n);
00152 memcpy((void *)(buf+HEADERSIZE), (const void *)indices, 4*n);
00153 memcpy((void *)(buf+HEADERSIZE+4*n), (const void *)forces, 12*n);
00154 int rc = (imd_writen(s, buf, size) != size);
00155 delete [] buf;
00156 return rc;
00157 }
00158
00159 int imd_send_energies(void *s, const IMDEnergies *energies) {
00160 int32 size = HEADERSIZE+sizeof(IMDEnergies);
00161 char *buf = new char[size];
00162 fill_header((IMDheader *)buf, IMD_ENERGIES, 1);
00163 memcpy((void *)(buf+HEADERSIZE), (const void *)energies, sizeof(IMDEnergies));
00164 int rc = (imd_writen(s, buf, size) != size);
00165 delete [] buf;
00166 return rc;
00167 }
00168
00169 int imd_send_fcoords(void *s, int32 n, const float *coords) {
00170 int32 size = HEADERSIZE+12*n;
00171 char *buf = new char[size];
00172 fill_header((IMDheader *)buf, IMD_FCOORDS, n);
00173 memcpy((void *)(buf+HEADERSIZE), (const void *)coords, 12*n);
00174 int rc = (imd_writen(s, buf, size) != size);
00175 delete [] buf;
00176 return rc;
00177 }
00178
00179
00180
00181
00182 IMDType imd_recv_header_nolengthswap(void *s, int32 *length) {
00183 IMDheader header;
00184 if (imd_readn(s, (char *)&header, HEADERSIZE) != HEADERSIZE)
00185 return IMD_IOERROR;
00186 *length = header.length;
00187 swap_header(&header);
00188 return IMDType(header.type);
00189 }
00190
00191 int imd_recv_handshake(void *s) {
00192
00193 if (vmdsock_selread(s, 5) != 1) return -1;
00194
00195
00196 int32 buf;
00197 IMDType type = imd_recv_header_nolengthswap(s, &buf);
00198 if (type != IMD_HANDSHAKE) return -1;
00199
00200
00201 if (buf == IMDVERSION) {
00202 if (!imd_go(s)) return 0;
00203 return -1;
00204 }
00205 swap4((char *)&buf, 4);
00206 if (buf == IMDVERSION) {
00207 if (!imd_go(s)) return 1;
00208 }
00209
00210
00211 return -1;
00212 }
00213
00214 IMDType imd_recv_header(void *s, int32 *length) {
00215 IMDheader header;
00216 if (imd_readn(s, (char *)&header, HEADERSIZE) != HEADERSIZE)
00217 return IMD_IOERROR;
00218 int i;
00219 char *ch = (char*)(&header);
00220 swap_header(&header);
00221 *length = header.length;
00222 return IMDType(header.type);
00223 }
00224
00225 int imd_recv_mdcomm(void *s, int32 n, int32 *indices, float *forces) {
00226 if (imd_readn(s, (char *)indices, 4*n) != 4*n) return 1;
00227 if (imd_readn(s, (char *)forces, 12*n) != 12*n) return 1;
00228 return 0;
00229 }
00230
00231 int imd_recv_energies(void *s, IMDEnergies *energies) {
00232 return (imd_readn(s, (char *)energies, sizeof(IMDEnergies))
00233 != sizeof(IMDEnergies));
00234 }
00235
00236 int imd_recv_fcoords(void *s, int32 n, float *coords) {
00237 return (imd_readn(s, (char *)coords, 12*n) != 12*n);
00238 }
00239