/* * mdclient.c * * Summary: Establish remote communication with server. * The client acts as an "engine" with respect to MDAPI. * * Author: David Hardy */ #include "mdremote.h" /* * prototypes for internal functions */ MD_Errcode MD_client_create_engine(MD_Sim *sim) { const char *engname = MD_engine_name(sim); char *hostname, *colon, *hashsym; MD_Int portnum = MD_DEFAULT_PORT; MD_Remote *client; const char *client_name = MD_API_NAME " Remote Communications Layer: Client"; /* parse host name and optional port number */ /* syntax is: hostname#1025:/abs/path/to/engine.so */ colon = strchr(engine_name, ':'); if (colon == NULL) { MD_ERR(sim, client_name, MD_ERR_CONNECT, "host is not given in engine name string"); return MD_FAIL; } /* must copy engname to hostname to finish parsing */ hostname = strdup(engname); if (hostname == NULL) { MD_ERR(sim, client_name, MD_ERR_MEMALLOC, strerror(errno)); return MD_FAIL; } hostname[colon - engname] = '\0'; /* colon - engname is index of ':' */ hashsym = strchr(hostname, '#'); if (hashsym != NULL) { portnum = (unsigned short) atoi(hashsym + 1); *hashsym = '\0'; } engname = colon + 1; /* allocate space for client and zero contents of object */ client = (MD_Remote *) calloc(1, sizeof(MD_Remote)); if (client == NULL) { MD_ERR(sim, client_name, MD_ERR_MEMALLOC, strerror(errno)); return MD_FAIL; } client->sim = sim; client->name = client_name; /* set version number and engine pointer */ if (MD_set_version(sim, MD_API_VERSION) || MD_set_engine(sim, client)) { return MD_FAIL; } /* try to connect to the server running on hostname */ if (MD_remote_client_connect(client, hostname, portnum)) return MD_FAIL; /* send CREATE message to server */ client->sendmsg[INDX_MSGID] = MSG_CREATE; client->sendmsg[INDX_VERSION] = MD_API_VERSION; client->sendmsg[INDX_ENGSTRZ] = strlen(engname) + 1; if (MD_remote_send(client, client->sendmsg, SZ_MSG_CREATE)) return MD_FAIL; /* send engine name string to server */ if (MD_remote_send(client, engname, client->sendmsg[INDX_ENGSTRZ])) { return MD_FAIL; } /* override the default MD_Sim methods */ if (MD_set_run(sim, run)) return MD_FAIL; if (MD_set_init(sim, init)) return MD_FAIL; if (MD_set_isdone(sim, isdone)) return MD_FAIL; if (MD_set_wait(sim, wait)) return MD_FAIL; if (MD_set_prcb(sim, prcb)) return MD_FAIL; if (MD_set_isdoneprcb(sim, isdoneprcb)) return MD_FAIL; if (MD_set_waitprcb(sim, waitprcb)) return MD_FAIL; /* setup to receive CREATE_ACK message */ free(hostname); return 0; } void MD_client_destroy_engine(MD_Sim *sim) { }