int tclcommand_imd_print_check_connect(Tcl_Interp *interp) { /* handshaking */ if (vmdsock_selread(initsock, 0) > 0) { int32_t length; sock = vmdsock_accept(initsock); if (imd_handshake(sock)) { Tcl_AppendResult(interp, "IMD handshake failed. Wrong VMD version ?", (char *) NULL); vmdsock_destroy(sock); sock = 0; return (TCL_ERROR); } sleep(1); if ((vmdsock_selread(sock, 0) != 1) || (imd_recv_header(sock, &length) != IMD_GO)) { Tcl_AppendResult(interp, "No go from VMD. Wrong VMD version ?", (char *) NULL); vmdsock_destroy(sock); sock = 0; return (TCL_ERROR); } sleep(1); } return (TCL_OK); }
int VMDCollab::connect(const char *host, int port) { if (clientsock) { msgErr << "Already connected to another vmdcollab server" << sendmsg; return FALSE; } if (!(clientsock = vmdsock_create())) { msgErr << "Could not create socket." << sendmsg; return FALSE; } int numTries = 3; for (int i=0; i<numTries; i++) { if (vmdsock_connect(clientsock, host, port)) { msgErr << "Could not connect to vmdcollab server at " << host << ":" << port << sendmsg; msgErr << "Error: " << strerror(errno) << sendmsg; } else { // success return TRUE; } // sleep for a second; maybe the server just hasn't started yet vmd_sleep(1); } // failed msgErr << "VMDCollab giving up after " << numTries << " seconds." << sendmsg; vmdsock_destroy(clientsock); clientsock = NULL; return FALSE; }
int VMDCollab::startserver(int port) { if (serversock) { msgErr << "Already running a server on port " << port << sendmsg; return FALSE; } void *serversock = vmdsock_create(); if (!serversock) { msgErr << "Could not create socket." << sendmsg; return FALSE; } if (vmdsock_bind(serversock, port)) { msgErr << "Could not bind vmdcollab server to port " << port << sendmsg; vmdsock_destroy(serversock); return FALSE; } vmdsock_listen(serversock); wkf_thread_t serverthread; if (wkf_thread_create(&serverthread, serverproc, // my thread routine serversock // context for thread )) { msgErr << "VMDCollab: unable to create server thread" << sendmsg; } else { msgInfo << "Starting VMDCollab bounce server." << sendmsg; } return TRUE; }
int VMDCollab::check_event() { if (!clientsock) return FALSE; eval_in_progress = TRUE; char buf[VMDCOLLAB_MSGSIZE]; while (vmdsock_selread(clientsock, 0) > 0) { if (imd_readn(clientsock, buf, VMDCOLLAB_MSGSIZE) != VMDCOLLAB_MSGSIZE) { vmdsock_shutdown(clientsock); vmdsock_destroy(clientsock); clientsock = NULL; break; } runcommand(new TclEvalEvent(buf)); } eval_in_progress = FALSE; return TRUE; }
int tclcommand_imd_print_drain_socket(Tcl_Interp *interp) { while (vmdsock_selread(sock,0) > 0) { int32_t length; IMDType type = imd_recv_header(sock, &length); switch (type) { case IMD_MDCOMM: /* ignore forces for now */ Tcl_AppendResult(interp, "IMD force feedback not yet implemented", (char *) NULL); return (TCL_ERROR); /* Expect the msglength to give number of indicies, and the data message to consist of first the indicies, then the coordinates in xyz1 xyz2... format. int32_t *addindices = new int32_t[length]; float *addforces = new float[3*length]; if (imd_recv_mdcomm(sock, length, addindices, addforces)) throw Error(IOERROR); oversized tmp buffer int32_t *tmpindices = new int32_t[n_atoms + length]; float *tmpforces = new float[3*(n_atoms + length)]; int32_t tmpatoms = n_atoms; for (int i = 0; i < tmpatoms; i++) { tmpindices[i] = indices[i]; tmpforces[3*i ] = forces[3*i]; tmpforces[3*i + 1] = forces[3*i + 1]; tmpforces[3*i + 2] = forces[3*i + 2]; } for (int i = 0; i < length; i++) { int32_t index = addindices[i]; check if there is a force for this atom already int j; for (j = 0; j < tmpatoms; j++) if (tmpindices[j] == index) break; if (j == tmpatoms) { tmpindices[j] = index; tmpatoms++; } tmpforces[3*j ] = addforces[3*i ]; tmpforces[3*j + 1] = addforces[3*i + 1]; tmpforces[3*j + 2] = addforces[3*i + 2]; } if (n_atoms > 0) { delete[] indices; delete[] forces; } n_atoms = tmpatoms; indices = new int32_t[n_atoms]; forces = new float[3*n_atoms]; cout << "now forces are" << endl; for (int i = 0; i < n_atoms; i++) { indices[i] = tmpindices[i]; forces[3*i ] = tmpforces[3*i]; forces[3*i + 1] = tmpforces[3*i + 1]; forces[3*i + 2] = tmpforces[3*i + 2]; cout << indices[i] << " force " << forces[3*i ] << " " << forces[3*i + 1] << " " << forces[3*i + 2] << endl; } cout << "end" << endl; */ break; case IMD_TRATE: transfer_rate = length; break; case IMD_IOERROR: vmdsock_destroy(sock); sock = 0; Tcl_AppendResult(interp, "IMD reports IO error", (char *) NULL); return (TCL_ERROR); case IMD_DISCONNECT: case IMD_KILL: vmdsock_destroy(sock); sock = 0; Tcl_AppendResult(interp, "no connection", (char *) NULL); return (TCL_OK); case IMD_ENERGIES: case IMD_FCOORDS: Tcl_AppendResult(interp, "IMD protocol failure: unexpected token.", (char *) NULL); return (TCL_ERROR); break; default: ; } } return (TCL_OK); }
int tclcommand_imd(ClientData data, Tcl_Interp *interp, int argc, char **argv) { if (argc < 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " connect|disconnect|listen|positions|energies ?values?\"", (char *) NULL); return (TCL_ERROR); } if (ARG1_IS_S("connect")) { /* connect to vmd */ int port = 12346; if (argc > 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " connect ?port?\"", (char *) NULL); return (TCL_ERROR); } if (argc == 3) if (!ARG_IS_I(2, port)) return (TCL_ERROR); if (sock) vmdsock_destroy(sock); if (initsock) vmdsock_destroy(initsock); sock = 0; initsock = 0; vmdsock_init(); initsock = vmdsock_create(); if (vmdsock_bind(initsock, port) != 0) { Tcl_AppendResult(interp, "IMD bind failed. Port already in use ?", (char *) NULL); vmdsock_destroy(initsock); initsock = 0; return (TCL_ERROR); } if (vmdsock_listen(initsock)) { Tcl_AppendResult(interp, "IMD listen failed. Port already in use ?", (char *) NULL); vmdsock_destroy(initsock); initsock = 0; return (TCL_ERROR); } return (TCL_OK); } if (ARG1_IS_S("disconnect")) { if (argc > 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " disconnect\"", (char *) NULL); return (TCL_ERROR); } if (sock) vmdsock_destroy(sock); if (initsock) vmdsock_destroy(initsock); sock = 0; initsock = 0; Tcl_AppendResult(interp, "no connection", (char *) NULL); return (TCL_OK); } if (ARG1_IS_S("listen")) { /* wait until vmd connects */ int cnt = 3600; if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " listen <secs>\"", (char *) NULL); return (TCL_ERROR); } if (!ARG_IS_I(2, cnt)) return (TCL_ERROR); while (initsock && !sock && cnt--) { if (tclcommand_imd_print_check_connect(interp) == TCL_ERROR) return (TCL_ERROR); sleep(1); } if (!sock) Tcl_AppendResult(interp, "no connection", (char *) NULL); else { if (tclcommand_imd_print_drain_socket(interp) == TCL_ERROR) return (TCL_ERROR); Tcl_AppendResult(interp, "connected", (char *) NULL); } return (TCL_OK); } if (ARG1_IS_S("positions")) return tclcommand_imd_parse_pos(interp, argc, argv); if (ARG1_IS_S("energies")) { Tcl_AppendResult(interp, "Sorry. imd energies not yet implemented", (char *) NULL); return (TCL_ERROR); } Tcl_AppendResult(interp, "imd: unkown job.", (char *) NULL); return (TCL_ERROR); }
void *VMDCollab::serverproc(void *serversock) { ResizeArray<void *>clients; char buf[VMDCOLLAB_MSGSIZE]; int i, j; while (1) { // if we have no clients, hang until someone connects // otherwise, just check for pending connections if (vmdsock_selread(serversock, 0) > 0) { msgInfo << "serversock became readable" << sendmsg; void *clientsock = vmdsock_accept(serversock); if (clientsock) { msgInfo << "VMDCollab accepting connection" << sendmsg; clients.append(clientsock); } } else if (vmdsock_selwrite(serversock, 0)) { msgInfo << "serversock became writable; exiting..." << sendmsg; break; } // Loop through one socket at a time. If incoming data is found, // drain it before moving on, on the assumption that we only want // commands from one VMD at a time to be propagated to the other // clients. for (i=0; i<clients.num(); i++) { void *client = clients[i]; while (vmdsock_selread(client, 0) > 0) { memset(buf, 0, VMDCOLLAB_MSGSIZE); if (imd_readn(client, buf, VMDCOLLAB_MSGSIZE) != VMDCOLLAB_MSGSIZE) { msgInfo << "client sent incomplete message, shutting it down" << sendmsg; vmdsock_shutdown(client); vmdsock_destroy(client); clients.remove(clients.find(client)); break; } // send to all other clients for (j=0; j<clients.num(); j++) { void *dest = clients[j]; if (dest != client) { imd_writen(clients[j], buf, VMDCOLLAB_MSGSIZE); } } // loop over clients other than sender } // while client is readable } // loop over clients vmd_msleep(10); } // if here, then the serversock got shut down, indicating that it's // time to die. msgInfo << "VMDCollab shutting down server" << sendmsg; for (i=0; i<clients.num(); i++) { void *client = clients[i]; strcpy(buf, "exit"); imd_writen(client, buf, VMDCOLLAB_MSGSIZE); vmdsock_shutdown(client); vmdsock_destroy(client); } vmdsock_destroy(serversock); return NULL; }
void VMDCollab::disconnect() { if (!clientsock) return; vmdsock_shutdown(clientsock); vmdsock_destroy(clientsock); clientsock = NULL; }
void IMD::receive(){ if(!connected) return; if(clientsock){ IMDType type; int length; int itype; while (vmdsock_selread(clientsock,0) > 0) { type = imd_recv_header(clientsock, &length); if(type==IMD_MDCOMM){ int32* vmd_atoms = new int32[length]; float* vmd_forces = new float[3*length]; imd_recv_mdcomm(clientsock, length, vmd_atoms, vmd_forces); for(int i=0;i<length;i++){ forces[3*vmd_atoms[i]+0]=vmd_forces[3*i+0]; forces[3*vmd_atoms[i]+1]=vmd_forces[3*i+1]; forces[3*vmd_atoms[i]+2]=vmd_forces[3*i+2]; } delete [] vmd_atoms; delete [] vmd_forces; itype=0; comm.Bcast(&itype,1,0); comm.Bcast(&forces[0],forces.size(),0); }else if(type==IMD_DISCONNECT){ vmdsock_destroy(clientsock); clientsock=NULL; for(unsigned i=0;i<forces.size();i++) forces[i]=0.0; connected=false; itype=1; comm.Bcast(&itype,1,0); break; }else if(type==IMD_TRATE){ if(length<1) length=1; itype=2; log.printf("IMD: setting transfer rate to %d\n",length); transferRate=length; comm.Bcast(&itype,1,0); comm.Bcast(&transferRate,1,0); }else if(type==IMD_KILL){ log.printf("IMD: killing simulation\n"); itype=3; comm.Bcast(&itype,1,0); plumed.exit(); } } itype=-1; comm.Bcast(&itype,1,0); } if(comm.Get_rank()!=0){ int itype; while(true){ comm.Bcast(&itype,1,0); if(itype==-1)break; else if(itype==0) comm.Bcast(&forces[0],forces.size(),0); else if(itype==1) { for(unsigned i=0;i<forces.size();i++) forces[i]=0.0; connected=false; } else if(itype==2) comm.Bcast(&transferRate,1,0); else if(itype==3) plumed.exit(); else plumed_error(); } } }