/* TODO: support multi-line reply */ static s32 write_reply(client_t *client, u16 code, char *msg) { u32 msglen = 4 + strlen(msg) + CRLF_LENGTH; char * msgbuf = (char *) malloc(msglen + 1); if (msgbuf == NULL) return -ENOMEM; sprintf(msgbuf, "%u %s\r\n", code, msg); gxprintf("Wrote reply: %s", msgbuf); s32 ret = send_exact(client->socket, msgbuf, msglen); free(msgbuf); return ret; }
s32 send_from_file(s32 s, FILE *f) { char * buf = (char *) malloc(FREAD_BUFFER_SIZE); if(!buf) return -1; s32 bytes_read; s32 result = 0; bytes_read = fread(buf, 1, FREAD_BUFFER_SIZE, f); if (bytes_read > 0) { result = send_exact(s, buf, bytes_read); if (result < 0) goto end; } if (bytes_read < FREAD_BUFFER_SIZE) { result = -!feof(f); goto end; } free(buf); return -EAGAIN; end: free(buf); return result; }
void * server_io_loop(void * arg) { int listenfd = -1, connfd = -1; struct sockaddr_in serv_addr; //Network socket, TCP streaming protocol, default options listenfd = socket(AF_INET, SOCK_STREAM, 0); NBDEBUG( "log_streamio listenfd=[%i]\n", listenfd); //memset(&serv_addr, '0', sizeof(serv_addr)); memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(STREAM_PORT); bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); //Accepting connections on this socket, no backqueue listen(listenfd, 0); NBDEBUG("log_streamio listening...port=%i\n", STREAM_PORT); control::flags[control::serv_connected] = false; for (;;) { connfd = block_accept(listenfd, STREAM_USLEEP_WAITING); Log * obj = NULL; int obj_bi = -1; NBDEBUG("log_streamio FOUND CLIENT [%i]\n", connfd); memcpy(cio_start, total, sizeof(io_state_t) * NUM_LOG_BUFFERS); cio_upstart = time(NULL); control::flags[control::serv_connected] = true; uint32_t version = htonl(LOG_VERSION); uint32_t seq_num = 0; uint32_t recvd; int ourVersion, thmVersion; CHECK_RET(send_exact(connfd, 4, (uint8_t *) &seq_num)) CHECK_RET(recv_exact(connfd, 4, (uint8_t *) &recvd, IO_SEC_TO_BREAK)); if (recvd != 0) { NBDEBUG( "log_streamio got bad ping initiation: %u\n", ntohl(recvd)); goto connection_died; } CHECK_RET(send_exact(connfd, 4, (uint8_t *) &version)) CHECK_RET(recv_exact(connfd, 4, (uint8_t *) &recvd, IO_SEC_TO_BREAK)); ourVersion = ntohl(version); thmVersion = ntohl(recvd); /* NBDEBUG( "log_streamio starting connection; server version: %u, client version: %u\n", ourVersion, thmVersion); */ NBDEBUG( "log_streamio starting connection; server version: %u, client version: %u\n", ntohl(version), ntohl(recvd)); ++seq_num; for (;;) { //we're writing. uint8_t ws = false; for (int i = 0; i < NUM_LOG_BUFFERS; ++i) { obj_bi = i; for (int r = 0; r < LOG_RATIO[i]; ++r) { obj = acquire(i, &(log_main.buffers[i].servio_nextr)); if (obj) { ws = true; uint32_t msg_seq_n = htonl(seq_num++); CHECK_RET(send_exact(connfd, 4, (uint8_t *) &msg_seq_n)); CHECK_RET(!obj->send(connfd)); releaseWrapper(i, obj, true); } else { break; } obj = NULL; } } if (!ws) { int32_t zero = 0, resp; CHECK_RET( send_exact(connfd, 4, &zero) ); CHECK_RET( recv_exact(connfd, 4, &resp, IO_SEC_TO_BREAK) ); if (zero != resp) { goto connection_died; } usleep(STREAM_USLEEP_WAITING); } } //Acts like a c exception. connection_died: close(connfd); NBDEBUG( "log_streamio loop broken, connection closed.\n"); control::flags[control::serv_connected] = false; if (obj) releaseWrapper(obj_bi, obj, true); obj = NULL; } return NULL; }