📄 tftpserver.c
字号:
if (errno || !req->file) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(2); strcpy(req->serverError.errormessage, "Invalid Path or No Access"); logMess_2(req, 1); req->bytesSent = send(req->m_socket, (const char*) & (req->serverError), strlen(req->serverError.errormessage) + 5, 0); cleanReq(req); pthread_exit(NULL); } } if (ntohs(req->datain.opcode) == 1) //handle RRQ { //allocate memory for req->pkt. errno = 0; req->pkt = (struct packet *)malloc(req->blksize + 4); if (errno || !req->pkt) { sprintf(logBuff,"Memory Error"); logMess(1); req->attempt = 255; cleanReq(req); pthread_exit(NULL); } if (ftell(req->file)) fseek(req->file, 0, SEEK_SET); // send DATA(1) errno = 0; req->block = 1; req->pkt->opcode = htons(3); req->pkt->block = htons(req->block); req->bytesRead = fread(&req->pkt->buffer, 1, req->blksize, req->file); if (errno) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(0); sprintf(req->serverError.errormessage, "%s", strerror(errno)); logMess_2(req, 1); req->bytesSent = send(req->m_socket, (const char*) & (req->serverError), strlen(req->serverError.errormessage) + 5, 0); cleanReq(req); pthread_exit(NULL); } req->bytesSent = send(req->m_socket, (const char*)req->pkt, req->bytesRead + 4, 0); req->fblock++; if (errno) { sprintf(req->serverError.errormessage, "Communication Error"); logMess_2(req, 1); cleanReq(req); pthread_exit(NULL); } //if it reaches the end of file, close file. if (req->bytesRead != req->blksize) { fclose(req->file); req->file = 0; } while (1) { //try to get response from client. FD_ZERO(&req->readfds); req->tv.tv_sec = req->interval; req->tv.tv_usec = 0; FD_SET(req->m_socket, &req->readfds); select(req->m_socket + 1, &req->readfds, NULL, NULL, &req->tv); if (FD_ISSET(req->m_socket, &req->readfds)) { //get response from client. errno = 0; req->bytesReceived = recv(req->m_socket, (char*) & (req->datain), sizeof(struct ack), 0); if (errno) { sprintf(req->serverError.errormessage, "Communication Error"); logMess_2(req, 1); cleanReq(req); pthread_exit(NULL); } } else req->bytesReceived = 0; //no client response available. if (req->bytesReceived >= 4) { //the ACK frame is what we expected. if (ntohs(req->datain.opcode) == 4) { if (ntohs(req->datain.block) == req->block) { //the block is what we expected. req->block++; req->attempt = 0; if (req->file) { //if there are still datus to send, continue. //read data from file and put it into req->pkt. errno = 0; req->pkt->opcode = htons(3); req->pkt->block = htons(req->block); req->bytesRead = fread(&req->pkt->buffer, 1, req->blksize, req->file); if (errno) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(0); sprintf(req->serverError.errormessage, "%s", strerror(errno)); logMess_2(req, 1); req->bytesSent = send(req->m_socket, (const char*) & (req->serverError), strlen(req->serverError.errormessage) + 5, 0); cleanReq(req); pthread_exit(NULL); } //send req->pkt. req->bytesSent = send(req->m_socket, (const char*)req->pkt, req->bytesRead + 4, 0); req->fblock++; if (errno) { sprintf(req->serverError.errormessage, "Communication Error"); logMess_2(req, 1); cleanReq(req); pthread_exit(NULL); } //if it reaches the end of file, close file. if (req->bytesRead != req->blksize) { fclose(req->file); req->file = 0; } } else { sprintf(logBuff, "Client %s:%u %s, %u Blocks Served", inet_ntoa(req->client.sin_addr), ntohs(req->client.sin_port), req->path, req->fblock); logMess(2); req->attempt = 255; break; } } else continue; } else if (ntohs(req->datain.opcode) == 5) { sprintf(req->serverError.errormessage, "Client %s:%u, Error Code %i at Client, %s", inet_ntoa(req->client.sin_addr), ntohs(req->client.sin_port), ntohs(req->clientError.errorcode), req->clientError.errormessage); logMess_2(req, 1); cleanReq(req); pthread_exit(NULL); } else { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(0); strcpy(req->serverError.errormessage, "Unexpected Option Code"); logMess_2(req, 1); req->bytesSent = send(req->m_socket, (const char*) & (req->serverError), strlen(req->serverError.errormessage) + 5, 0); cleanReq(req); pthread_exit(NULL); } } else if (req->attempt >= 3) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(0); strcpy(req->serverError.errormessage, "Timeout"); logMess_2(req, 1); req->bytesSent = send(req->m_socket, (const char*) & (req->serverError), strlen(req->serverError.errormessage) + 5, 0); cleanReq(req); pthread_exit(NULL); } else { //resend previous frame. errno = 0; req->bytesSent = send(req->m_socket, (const char*)req->pkt, req->bytesSent, 0); req->attempt++; if (errno) { sprintf(req->serverError.errormessage, "Communication Error"); logMess_2(req, 1); cleanReq(req); pthread_exit(NULL); } } } } else if (ntohs(req->datain.opcode) == 2) //handle WRQ { //send ACK(0) to client. req->block = 0; req->acout.opcode = htons(4); req->acout.block = htons(req->block); errno = 0; req->bytesSent = send(req->m_socket, (const char*) & (req->acout), 4, 0); if (errno) { sprintf(req->serverError.errormessage, "Communication Error"); logMess_2(req, 1); cleanReq(req); pthread_exit(NULL); } errno = 0; req->pkt = (struct packet *)malloc(req->blksize + 4); if (errno || !req->pkt) { sprintf(logBuff,"Memory Error"); logMess(1); req->attempt = 255; cleanReq(req); pthread_exit(NULL); } while (1) { //try to get response from client. FD_ZERO(&req->readfds); req->tv.tv_sec = req->interval; req->tv.tv_usec = 0; FD_SET(req->m_socket, &req->readfds); select(req->m_socket + 1, &req->readfds, NULL, NULL, &req->tv); if (FD_ISSET(req->m_socket, &req->readfds)) { //get response from client. errno = 0; req->bytesReceived = recv(req->m_socket, (char*)req->pkt, req->blksize + 4, 0); if (errno) { sprintf(req->serverError.errormessage, "Communication Error"); logMess_2(req, 1); cleanReq(req); pthread_exit(NULL); } } else req->bytesReceived = 0; //no client response available. if (req->bytesReceived >= 4) { if (ntohs(req->pkt->opcode) == 3) { //the opcode(DATA) is what we expected. if (ntohs(req->pkt->block) == req->block + 1) { //the block is what we expected, send ACK to client. req->acout.opcode = htons(4); req->acout.block = htons(req->block + 1); req->block++; errno = 0; req->bytesSent = send(req->m_socket, (const char*)&req->acout, 4, 0); if (errno ) { sprintf(req->serverError.errormessage, "Communication Error"); logMess_2(req, 1); cleanReq(req); pthread_exit(NULL); } if (req->file && req->bytesReceived > 4) { errno = 0; fwrite(&req->pkt->buffer, req->bytesReceived - 4, 1, req->file); if (errno) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(3); strcpy(req->serverError.errormessage, "Disk full or allocation exceeded"); logMess_2(req, 1); req->bytesSent = send(req->m_socket, (const char*) & (req->serverError), strlen(req->serverError.errormessage) + 5, 0); cleanReq(req); pthread_exit(NULL); } else { req->fblock++; req->attempt = 0; } } if (req->bytesReceived - 4 < req->blksize) { fclose(req->file); req->file = 0; sprintf(logBuff, "Client %s:%u %s, %u Blocks Received", inet_ntoa(req->client.sin_addr), ntohs(req->client.sin_port), req->path, req->fblock); logMess(2); break; } } else continue; } else if (ntohs(req->pkt->opcode) == 5) { sprintf(logBuff, "Error Code %i at Client, %s", ntohs(req->clientError.errorcode), req->clientError.errormessage); logMess(1); cleanReq(req); pthread_exit(NULL); } else { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(4); strcpy(req->serverError.errormessage, "Unexpected Option Code"); logMess_2(req, 1); req->bytesSent = send(req->m_socket, (const char*) & (req->serverError), strlen(req->serverError.errormessage) + 5, 0); cleanReq(req); pthread_exit(NULL); } } else if (req->attempt >= 3) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(0); strcpy(req->serverError.errormessage, "Timeout"); logMess_2(req, 1); req->bytesSent = send(req->m_socket, (const char*) & (req->serverError), strlen(req->serverError.errormessage) + 5, 0); cleanReq(req); pthread_exit(NULL); } else { errno = 0; send(req->m_socket, (const char*)&req->acout, req->bytesSent, 0); req->attempt++; if (errno ) { sprintf(req->serverError.errormessage, "Communication Error"); logMess_2(req, 1); cleanReq(req); pthread_exit(NULL); } } } } cleanReq(req); pthread_exit(NULL);}void cleanReq(struct request* req){printf("tid[%d] cleanReq executed .\n", req->threadId); if (req->file) { fclose(req->file); req->file = 0; } if (req->m_socket >= 0) { close(req->m_socket); req->m_socket = 0; } if (req->pkt) { free(req->pkt); req->pkt = 0; } free(req); req = NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -