void readcb(int fd, int id, void* data) { struct client* c = data; if (c == NULL) { printf("id %d, NULL client read\n", id); return; } int error = NETEV_OK; for (;;) { struct msg_header* h = netev_read(s->ne, id, sizeof(struct msg_header)); if (h == NULL) { error = netev_error(s->ne); if (error == NETEV_OK) { goto out; } else { goto err_out; } } assert(h->size == package_size); uint32_t* msg = netev_read(s->ne, id, h->size); if (msg == NULL) { error = netev_error(s->ne); if (error == NETEV_OK) { goto out; } else { goto err_out; } } int i; for (i=0; i<h->size/sizeof(msg[0]); ++i) { assert(msg[i] == id); } //printf("from client %d, read msg size=%d\n", id, h->size); //_handle_msg(c, (void*)h, sizeof(*h) + h->size); netev_dropread(s->ne, id); s->rstat += 1; } out: return; err_out: printf("client %d read occur error %d\n", id, error); _free_client(s, c); s->nclosedread +=1; return; }
// Handshake with client and attach to PSL static struct client *_client_connect(int *fd, char *ip) { struct client *client; uint8_t buffer[MAX_LINE_CHARS]; uint8_t ack[3]; uint16_t map; int rc; // Parse client handshake data ack[0] = PSLSE_DETACH; memset(buffer, '\0', MAX_LINE_CHARS); rc = get_bytes(*fd, 5, buffer, timeout, 0, fp, -1, -1); if ((rc < 0) || (strcmp((char *)buffer, "PSLSE"))) { info_msg("Connecting application is not PSLSE client\n"); info_msg("Expected: \"PSLSE\" Got: \"%s\"", buffer); put_bytes(*fd, 1, ack, fp, -1, -1); close_socket(fd); return NULL; } rc = get_bytes_silent(*fd, 2, buffer, timeout, 0); if ((rc < 0) || ((uint8_t) buffer[0] != PSLSE_VERSION_MAJOR) || ((uint8_t) buffer[1] != PSLSE_VERSION_MINOR)) { info_msg("Client is wrong version\n"); put_bytes(*fd, 1, ack, fp, -1, -1); close_socket(fd); return NULL; } // Initialize client struct client = (struct client *)calloc(1, sizeof(struct client)); client->fd = *fd; client->ip = ip; client->pending = 1; client->timeout = timeout; client->flushing = FLUSH_NONE; client->state = CLIENT_INIT; // Return acknowledge to client ack[0] = PSLSE_CONNECT; map = htons(afu_map); memcpy(&(ack[1]), &map, sizeof(map)); if (put_bytes(client->fd, 3, ack, fp, -1, -1) < 0) { _free_client(client); return NULL; } info_msg("%s connected", client->ip); return client; }
void _start_write(struct server* s) { int i; int j; int size = package_size + sizeof(struct msg_header); char data[size]; struct msg_header* m = (struct msg_header*)data; m->size = package_size; for (i=0; i<s->max; ++i) { struct client* c = &s->clients[i]; if (_is_client_closed(c)) continue; for (j=0; j<m->size/sizeof(m->text[0]); ++j) { m->text[j] = c->conn_id; } if (_start_write_client(c, m, size) != 0) { netev_close_socket(s->ne, c->conn_id); _free_client(s, c); s->nclosedwrite +=1; } } }
static void *fserv_thread_function(void *arg) { fserve_t *fclient, **trail; int sbytes, bytes; INFO0("file serving thread started"); while (run_fserv) { wait_for_fds(); fclient = active_list; trail = &active_list; while (fclient) { /* process this client, if it is ready */ if (fclient->ready) { fclient->ready = 0; if(fclient->offset >= fclient->datasize) { /* Grab a new chunk */ bytes = fread(fclient->buf, 1, BUFSIZE, fclient->file); if (bytes == 0) { fserve_t *to_go = fclient; fclient = fclient->next; *trail = fclient; _free_client (to_go); fserve_clients--; client_tree_changed = 1; continue; } fclient->offset = 0; fclient->datasize = bytes; } /* Now try and send current chunk. */ sbytes = client_send_bytes (fclient->client, &fclient->buf[fclient->offset], fclient->datasize - fclient->offset); /* TODO: remove clients if they take too long. */ if(sbytes > 0) { fclient->offset += sbytes; } if (fclient->client->con->error) { fserve_t *to_go = fclient; fclient = fclient->next; *trail = fclient; fserve_clients--; _free_client (to_go); client_tree_changed = 1; continue; } } trail = &fclient->next; fclient = fclient->next; } } /* Shutdown path */ thread_mutex_lock (&pending_lock); while (pending_list) { fserve_t *to_go = (fserve_t *)pending_list; pending_list = to_go->next; _free_client (to_go); } thread_mutex_unlock (&pending_lock); while (active_list) { fserve_t *to_go = active_list; active_list = to_go->next; _free_client (to_go); } return NULL; }
void writecb(int fd, int id, void* data) { struct client* c = data; if (c == NULL) { printf("id %d, NULL client write\n", id); return; } struct netbuf_block* wbuf_b = c->wbuf_b; if (wbuf_b->roffset == wbuf_b->woffset) { return; // empty } int error; if (wbuf_b->roffset < wbuf_b->woffset) { void* buf = (void*)wbuf_b + sizeof(*wbuf_b) + wbuf_b->roffset; int nbyte = netev_write(s->ne, id, buf, wbuf_b->woffset - wbuf_b->roffset); if (nbyte == -1) { goto err_out; } if (nbyte > 0) { wbuf_b->roffset += nbyte; c->stat_write += nbyte; goto out; } } else { void* begin = (void*)wbuf_b + sizeof(*wbuf_b); void* buf = begin + wbuf_b->roffset; int wsize = wbuf_b->size - wbuf_b->roffset; int nbyte = netev_write(s->ne, id, buf, wsize); if (nbyte == -1) { goto err_out; } if (nbyte == 0) { goto out; } c->stat_write += nbyte; if (nbyte < wsize) { wbuf_b->roffset += nbyte; goto out; } wbuf_b->roffset = 0; wsize = wbuf_b->woffset; if (wsize == 0) { goto out; } nbyte = netev_write(s->ne, id, begin, wsize); if (nbyte == -1) { goto err_out; } if (nbyte > 0) { wbuf_b->roffset += nbyte; c->stat_write += nbyte; goto out; } } out: //printf("write size=%d, woffset=%d roffset=%d\n", //c->stat_write - oldstat, wbuf_b->woffset, wbuf_b->roffset); return; err_out: error = netev_error(s->ne); printf("client %d, write occur error %d\n", id, error); _free_client(s, c); s->nclosedwrite +=1; }
int main(int argc, char **argv) { struct sockaddr_in client_addr; struct client *client; struct client **client_ptr; int listen_fd, connect_fd; socklen_t client_len; sigset_t set; struct sigaction action; char *shim_host_path; char *parms_path; char *debug_log_path; struct parms *parms; char *ip; // Open debug.log file debug_log_path = getenv("DEBUG_LOG_PATH"); if (!debug_log_path) debug_log_path = "debug.log"; fp = fopen(debug_log_path, "w"); if (!fp) { error_msg("Could not open debug.log"); return -1; } // Mask SIGPIPE signal for all threads sigemptyset(&set); sigaddset(&set, SIGPIPE); if (pthread_sigmask(SIG_BLOCK, &set, NULL)) { perror("pthread_sigmask"); return -1; } // Catch SIGINT for graceful termination action.sa_handler = _INThandler; sigemptyset(&(action.sa_mask)); action.sa_flags = 0; sigaction(SIGINT, &action, NULL); // Report version info_msg("PSLSE version %d.%03d compiled @ %s %s", PSLSE_VERSION_MAJOR, PSLSE_VERSION_MINOR, __DATE__, __TIME__); debug_send_version(fp, PSLSE_VERSION_MAJOR, PSLSE_VERSION_MINOR); // Parse parameters file parms_path = getenv("PSLSE_PARMS"); if (!parms_path) parms_path = "pslse.parms"; parms = parse_parms(parms_path, fp); if (parms == NULL) { error_msg("Unable to parse params file \"%s\"", parms_path); return -1; } timeout = parms->timeout; // Connect to simulator(s) and start psl thread(s) pthread_mutex_init(&lock, NULL); pthread_mutex_lock(&lock); shim_host_path = getenv("SHIM_HOST_DAT"); if (!shim_host_path) shim_host_path = "shim_host.dat"; afu_map = parse_host_data(&psl_list, parms, shim_host_path, &lock, fp); if (psl_list == NULL) { free(parms); fclose(fp); warn_msg("Unable to connect to any simulators"); return -1; } // Start server if ((listen_fd = _start_server()) < 0) { free(parms); fclose(fp); return -1; } // Watch for client connections while (psl_list != NULL) { // Wait for next client to connect client_len = sizeof(client_addr); pthread_mutex_unlock(&lock); connect_fd = accept(listen_fd, (struct sockaddr *)&client_addr, &client_len); pthread_mutex_lock(&lock); if (connect_fd < 0) { lock_delay(&lock); continue; } ip = (char *)malloc(INET_ADDRSTRLEN + 1); inet_ntop(AF_INET, &(client_addr.sin_addr.s_addr), ip, INET_ADDRSTRLEN); // Clean up disconnected clients client_ptr = &client_list; while (*client_ptr != NULL) { client = *client_ptr; if ((client->pending == 0) && (client->state == CLIENT_NONE)) { *client_ptr = client->_next; if (client->_next != NULL) client->_next->_prev = client->_prev; _free_client(client); lock_delay(&lock); continue; } client_ptr = &((*client_ptr)->_next); } // Add new client info_msg("Connection from %s", ip); client = _client_connect(&connect_fd, ip); if (client != NULL) { if (client_list != NULL) client_list->_prev = client; client->_next = client_list; client_list = client; if (pthread_create(&(client->thread), NULL, _client_loop, client)) { perror("pthread_create"); break; } } lock_delay(&lock); } info_msg("No AFUs connected, Shutting down PSLSE\n"); close_socket(&listen_fd); // Shutdown unassociated client connections while (client_list != NULL) { client = client_list; client_list = client->_next; if (client->pending) client->pending = 0; pthread_mutex_unlock(&lock); pthread_join(client->thread, NULL); pthread_mutex_lock(&lock); close_socket(&(client->fd)); _free_client(client); } pthread_mutex_unlock(&lock); free(parms); fclose(fp); pthread_mutex_destroy(&lock); return 0; }