// Loop for communication with last sensor void last_loop() { print_info("Last loop"); while(1) { if(mode == RECONF) { sleep(1); continue; } print_info("Waiting for data from last..."); unsigned char buf[MAX_DATA]; unsigned last_addr_len = sizeof(last_addr); int len = recvfrom(sock_last, buf, MAX_DATA, 0, (struct sockaddr*)&last_addr, &last_addr_len); if(len < 0) { mode = DOUBLE_LIST; resolving_error = 1; print_warning("Didn't receive data message from last sensor"); print_success("Mode changed to double-list"); if(send_error_msg(FIRST) < 0 || receive_ack_and_finit(FIRST) < 0) { close_first = 1; } if(send_error_msg(LAST) < 0 || receive_ack_and_finit(LAST) < 0) { resolving_error = 0; return; } resolving_error = 0; } else { union msg received_msg; int msg_type = unpack_msg(buf, &received_msg); switch(msg_type) { case INIT_MSG: take_init_msg(received_msg.init); break; case DATA_MSG: take_data_msg(received_msg.data); break; default: print_warning("Received unknown bytes"); } cleanup_msg(&received_msg); } usleep(SERVER_TIMEOUT*1000); if(mode == DOUBLE_LIST) { print_info("Sending data to last sensor..."); send_data_msg(LAST); } } }
/** @brief Handles HTTP GET requests. * Reads and parses the request, the uri, and dispatches the appropriate * functions to serve content. * @param conn_fd The connection file descriptor. * @return none. */ void handle_request(int conn_fd) { rio_t rio; char request[MAXLINE], uri[MAXLINE]; char file_name[MAXLINE], cgi_args[MAXLINE]; int is_static; struct stat st_buf; Rio_readinitb(&rio, conn_fd); /* Read first header line of incoming request. */ if (rio_readlineb(&rio, request, MAXLINE) < 0) { dbg_printf("rio_readlineb error\n"); return; } dbg_printf("Request: %s", request); if (parse_request_header(conn_fd, request, uri) != SUCCESS) { return; } if (read_request_headers(&rio) != SUCCESS) { return; } find_file(uri, file_name, cgi_args, &is_static); if (stat(file_name, &st_buf) < 0) { dbg_printf("404: File not found: %s\n", file_name); send_error_msg(conn_fd, "404", "File not found"); return; } /* Handle static content */ if (is_static) { if (!(S_ISREG(st_buf.st_mode)) || !(S_IRUSR & st_buf.st_mode)) { dbg_printf("403: Can't read the file: %s\n", file_name); send_error_msg(conn_fd, "403", "Can't read the file."); return; } serve_static(conn_fd, file_name, st_buf.st_size); } /* Handle dynamic content */ else { if (!(S_ISREG(st_buf.st_mode)) || !(S_IXUSR & st_buf.st_mode)) { dbg_printf("403: Can't run the CGI program: %s\n", file_name); send_error_msg(conn_fd, "403", "Can't run the CGI program."); return; } serve_dynamic(conn_fd, file_name, cgi_args); } }
int parse_request_header_bla(int conn_fd, char *request, char *uri) { char method[MAXLINE], version[MAXLINE]; /* Parse fields of incoming request. */ if (sscanf(request, "%s %s %s", method, uri, version) != 3) { dbg_printf("Error occured during parsing request\n"); return ERROR; } /* Only handles GET methods */ if (strcasecmp(method, "GET") != 0) { dbg_printf("501: The method %s is not handled\n", method); send_error_msg(conn_fd, "501", "Not implemented."); return ERROR; } /* Only handles HTTP/1.0 versions */ /* Not performing this check to be able to test with modern browsers. */ /* if (strcasecmp(version, "HTTP/1.0") != 0) { printf("501: The version %s is not handled\n", version); return ERROR; } */ return SUCCESS; }
void run_networking() { int udp_sockfd; int udp_portno; int udp_clientlen; struct sockaddr_in udp_serveraddr; struct sockaddr_in udp_clientaddr; struct hostent *udp_hostp; char buf[BUFSIZE]; char *udp_hostaddrp; int udp_optval; int n; udp_portno = atoi(param_udpport); udp_sockfd = socket(AF_INET, SOCK_DGRAM, 0); if(udp_sockfd < 0) { error("ERROR opening udp socket"); } udp_optval = 1; setsockopt(udp_sockfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&udp_optval, sizeof(int)); bzero((char *) &udp_serveraddr, sizeof(udp_serveraddr)); udp_serveraddr.sin_family = AF_INET; udp_serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); udp_serveraddr.sin_port = htons((unsigned short)udp_portno); if(bind(udp_sockfd, (struct sockaddr *)&udp_serveraddr, sizeof(udp_serveraddr)) < 0) { error("ERROR on udp binding"); } udp_clientlen = sizeof(udp_clientaddr); // cleanup players list cleanup_players(); int old_players_connected = 0; while(1) { bzero(buf, BUFSIZE); n = recvfrom(udp_sockfd, buf, BUFSIZE, 0, (struct sockaddr *)&udp_clientaddr, &udp_clientlen); if(n < 0) { error("ERROR in recvfrom"); } old_players_connected = players_connected; for(int i = 0; i < MAX_PLAYERS; i++) { if(!players[i].free) { if(abs(players[i].ping - time(0)) > PING_TIMEOUT / 2) { struct connect_four_packet_ping * packet_ping = malloc(sizeof(struct connect_four_packet_ping)); packet_ping->msg_code = MSG_PING; printf("PING %s %d\n", inet_ntoa(players[i].addr.sin_addr), ntohs(players[i].addr.sin_port)); players[i].ping = time(0); printf("PING diff %lu %lu\n", players[i].ping, players[i].pong); if(abs(players[i].ping - players[i].pong) >= PING_TIMEOUT) { players[i].free = 1; players_connected--; continue; } n = sendto(udp_sockfd, packet_ping, sizeof(*packet_ping), 0, &players[i].addr, sizeof(players[i].addr)); } } } if(old_players_connected > players_connected) { show_player_list(); } struct connect_four_packet_common *recvpacket = buf; printf("Got packet with message code: %ld\n", recvpacket->msg_code); switch(recvpacket->msg_code) { case MSG_PONG: { struct connect_four_packet_pong *packet_pong = recvpacket; for(int i = 0; i < MAX_PLAYERS; i++) { if((players[i].addr.sin_addr.s_addr == udp_clientaddr.sin_addr.s_addr) && (players[i].addr.sin_port == udp_clientaddr.sin_port)) { players[i].pong = time(0); } } } break; case MSG_JOIN: { if(game != NULL) { n = send_error_msg(udp_sockfd, "Game running. New clients are not allowed.", &udp_clientaddr, udp_clientlen, 1); break; } int free_slot_id = -1; int player_exists = 0; for(int i = 0; i < MAX_PLAYERS; i++) { if(players[i].free) { if(free_slot_id == -1) { free_slot_id = i; } } if((players[i].addr.sin_addr.s_addr == udp_clientaddr.sin_addr.s_addr) && (players[i].addr.sin_port == udp_clientaddr.sin_port)) { player_exists = 1; } } if(player_exists) { n = send_error_msg(udp_sockfd, "You are already registered for a game.", &udp_clientaddr, udp_clientlen, 0); } else if(free_slot_id == -1) { n = send_error_msg(udp_sockfd, "Game full. New clients are not allowed.", &udp_clientaddr, udp_clientlen, 2); } else { players_connected++; players[free_slot_id].addr.sin_family = AF_INET; players[free_slot_id].addr.sin_addr.s_addr = udp_clientaddr.sin_addr.s_addr; players[free_slot_id].addr.sin_port = udp_clientaddr.sin_port; players[free_slot_id].free = 0; players[free_slot_id].ready = 0; struct connect_four_packet_ok *packet_ok = malloc(sizeof(struct connect_four_packet_ok)); packet_ok->msg_code = MSG_OK; packet_ok->player_count = players_connected; packet_ok->player_id = players[free_slot_id].player_id; n = sendto(udp_sockfd, packet_ok, sizeof(*packet_ok), 0, (struct sockaddr *)&udp_clientaddr, udp_clientlen); free(packet_ok); } show_player_list(); } break; case MSG_READY: { int ready_players = 0; for(int i = 0; i < MAX_PLAYERS; i++) { if(!players[i].free) { if((players[i].addr.sin_addr.s_addr == udp_clientaddr.sin_addr.s_addr) && (players[i].addr.sin_port == udp_clientaddr.sin_port)) { players[i].ready = 1; } if(players[i].ready) { ready_players++; } } } printf("START ready_players %d players_connected %d", ready_players, players_connected); if((ready_players >= 2) && (players_connected == ready_players)) { /* * Everyone's ready, let's start the game! */ struct connect_four_packet_start *packet_start = malloc(sizeof(struct connect_four_packet_start)); packet_start->msg_code = MSG_START; switch(players_connected) { case 2: packet_start->column_count = 6; packet_start->row_count = 7; break; case 3: case 4: packet_start->column_count = 7; packet_start->row_count = 9; break; } game = newGame(packet_start->column_count, packet_start->row_count); game->players = players_connected; packet_start->player_count = players_connected; for(int i = 0; i < MAX_PLAYERS; i++) { if(!players[i].free) n = sendto(udp_sockfd, packet_start, sizeof(*packet_start), 0, &players[i].addr, sizeof(players[i].addr)); } free(packet_start); for(int i = 0; i < MAX_PLAYERS; i++) { if(!players[i].free) { if(players[i].player_id == (game->turn - '0')) { struct connect_four_packet_turn *packet_turn = malloc(sizeof(struct connect_four_packet_turn)); packet_turn->msg_code = MSG_TURN; sendto(udp_sockfd, packet_turn, sizeof(*packet_turn), 0, &players[i].addr, sizeof(players[i].addr)); free(packet_turn); break; } } } } show_player_list(); } break; case MSG_COLUMN: { if(game == NULL) { n = send_error_msg(udp_sockfd, "Game's not started yet.", &udp_clientaddr, udp_clientlen, 3); break; } int valid_player = 0; for(int i = 0; i < MAX_PLAYERS; i++) { if(!players[i].free) { if((players[i].addr.sin_addr.s_addr == udp_clientaddr.sin_addr.s_addr) && (players[i].addr.sin_port == udp_clientaddr.sin_port) && (players[i].player_id == (game->turn - '0'))) { int old_moves = game->moves; struct connect_four_packet_column *packet_column = buf; makeMove(game, packet_column->selected_column); char winner = hasWon(game, packet_column->selected_column); struct connect_four_packet_area *packet_area = malloc(sizeof(struct connect_four_packet_area)); packet_area->msg_code = MSG_AREA; game->array[game->height * game->width] = 0; strcpy(packet_area->area, game->array); printf("=======\n"); printf("Sending game data: %s", packet_area->area); printf("=======\n"); for(int i = 0; i < MAX_PLAYERS; i++) { if(!players[i].free) n = sendto(udp_sockfd, packet_area, sizeof(*packet_area), 0, &players[i].addr, sizeof(players[i].addr)); } free(packet_area); if((winner != 'f') || (game->moves == game->width * game->height)) { struct connect_four_packet_winner *packet_winner = malloc(sizeof(struct connect_four_packet_winner)); packet_winner->msg_code = MSG_WINNER; if(winner == 'f') { packet_winner->winner_id = 0; } else { packet_winner->winner_id = winner - '0'; } for(int i = 0; i < MAX_PLAYERS; i++) { if(!players[i].free) n = sendto(udp_sockfd, packet_winner, sizeof(*packet_winner), 0, &players[i].addr, sizeof(players[i].addr)); } free(packet_winner); cleanup_players(); free(game); game = NULL; } else { for(int i = 0; i < MAX_PLAYERS; i++) { if(!players[i].free) { if(players[i].player_id == (game->turn - '0')) { struct connect_four_packet_turn *packet_turn = malloc(sizeof(struct connect_four_packet_turn)); packet_turn->msg_code = MSG_TURN; sendto(udp_sockfd, packet_turn, sizeof(*packet_turn), 0, &players[i].addr, sizeof(players[i].addr)); free(packet_turn); break; } } } } if(game != NULL) { if(old_moves == game->moves) { n = send_error_msg(udp_sockfd, "Column full. Select another.", &udp_clientaddr, udp_clientlen, 4); break; } } valid_player = 1; break; } } } if(!valid_player) { n = send_error_msg(udp_sockfd, "It's not your turn!", &udp_clientaddr, udp_clientlen, 0); } } break; case MSG_QUIT: for(int i = 0; i < MAX_PLAYERS; i++) { printf("QUIT issued\n"); printf("%u\n = %u\n", players[i].addr.sin_addr.s_addr, udp_clientaddr.sin_addr.s_addr); printf("%hu\n = %hu\n", players[i].addr.sin_port, udp_clientaddr.sin_port); if((players[i].addr.sin_addr.s_addr == udp_clientaddr.sin_addr.s_addr) && (players[i].addr.sin_port == udp_clientaddr.sin_port)) { bzero((char *)&players[i].addr, sizeof(players[i].addr)); players[i].free = 1; players_connected--; } } show_player_list(); break; case MSG_CHAT_CLIENT: { struct connect_four_packet_chat_client * packet_chat_client = recvpacket; struct connect_four_packet_chat_server * packet_chat_server = malloc(sizeof(struct connect_four_packet_chat_server)); packet_chat_server->msg_code = MSG_CHAT_SERVER; strcpy(packet_chat_server->msg, packet_chat_client->msg); packet_chat_server->length = strlen(packet_chat_server->msg); for(int i = 0; i < MAX_PLAYERS; i++) { if((players[i].addr.sin_addr.s_addr == udp_clientaddr.sin_addr.s_addr) && (players[i].addr.sin_port == udp_clientaddr.sin_port)) { packet_chat_server->player_id = players[i].player_id; } } for(int i = 0; i < MAX_PLAYERS; i++) { if(!players[i].free) n = sendto(udp_sockfd, packet_chat_server, sizeof(*packet_chat_server), 0, &players[i].addr, sizeof(players[i].addr)); } free(packet_chat_server); } break; case MSG_CHAT_SERVER: // implemented case MSG_AREA: // implemented case MSG_TURN: // implemented case MSG_START: // implemented case MSG_OK: // implemented case MSG_WINNER: // implemented n = send_error_msg(udp_sockfd, "Got server-answer command from client.", &udp_clientaddr, udp_clientlen, 0); break; default: if(n < 2) { n = send_error_msg(udp_sockfd, "Unknown command received.", &udp_clientaddr, udp_clientlen, 0); } else { udp_hostp = gethostbyaddr((const char*)&udp_clientaddr.sin_addr.s_addr, sizeof(udp_clientaddr.sin_addr.s_addr), AF_INET); if(udp_hostp == NULL) { error("ERROR on gethostbyaddr"); } udp_hostaddrp = inet_ntoa(udp_clientaddr.sin_addr); if(udp_hostaddrp == NULL) { error("ERROR on inet_ntoa"); } n = sendto(udp_sockfd, buf, strlen(buf), 0, (struct sockaddr *)&udp_clientaddr, udp_clientlen); } break; } if(n < 0) { error("ERROR in sendto"); } } }
int wpc_mgr_procservermsg() { int nbytes; int written; int write_len; int fd; u_int8_t buf[MAX_PAYLOAD]={'\0'}; nbytes = wpc_recv(wpc_server_sock, buf, NSP_HDR_LEN, 0); struct nsp_header *nsp_header = (struct nsp_header *) buf; struct nsp_header nsp_hdr; int len = 0; //TBD: read length from frame header switch (nsp_header->frame_type) { case NSP_MRQST: len = MREQ_LEN; break; case NSP_SRQST: len = SREQ_LEN; break; case NSP_CRQST: len = CAPREQ_LEN; break; case NSP_WAKEUPRQST: len = WAKEUPREQ_LEN; break; case NSP_TSFRQST: len = TSFREQ_LEN; break; case NSP_STARETURNTOSLEEPREQ: len = SLEEPREQ_LEN; break; case NSP_WPCDBGRGST: len = WPCDBGREQ_LEN; break; } print_nsp_header(nsp_header); nbytes += wpc_recv(wpc_server_sock, buf+NSP_HDR_LEN, len, 0); if (nbytes <= 0) { //error or connection closed by client if (nbytes == 0) printf("selectserver: socket %d hung up\n", fdcount); else printf("recv failed\n"); wpc_close(wpc_server_sock); if(wpc_server_sock > 0) FD_CLR(wpc_server_sock, &read_fds); wpc_server_sock = -1; } else { buf[nbytes] = '\0'; struct nsp_mrqst *mrqst; struct nsp_sreq *srqst; struct nsp_cap_req *crqst; struct nsp_wakeup_req *wrqst; struct nsp_tsf_req *tsfrqst; struct nsp_sleep_req *slrqst; struct nsp_wpc_dbg_req *wpcdbgrqst; struct nsp_wpc_dbg_resp wpcdbgresp; struct request_no *reqno; struct timeval tv; time_t req_curtime; char time_buf[30]; reqno = (struct request_no *)(((char *)buf) + NSP_HDR_LEN); if( nsp_header->version > NSP_VERSION ) { printf("ERROR: Request protocol version no (%02x) > Current Version (%02x)\n",nsp_header->version, NSP_VERSION); send_error_msg(reqno->request_id, NSP_UNSUPPORTED_PROTOCOL_VERSION); return -1; } switch (nsp_header->frame_type) { case NSP_MRQST: mrqst = (struct nsp_mrqst *)(((char *)buf) + NSP_HDR_LEN); request_id = mrqst->request_id; if (wpc_debug) { if (wpc_dbg_log_len + WPCDBGHDR_LEN <= WPC_DBG_SIZE) { dump_wpc_log(__LINE__, nsp_header->frame_type); } else { printf("wpc log file is full:cannot written\n"); return; } } else { print_mrqst(mrqst); gettimeofday(&tv, NULL); req_curtime=tv.tv_sec; strftime(time_buf,30,"%m-%d-%Y %T.",localtime(&req_curtime)); PRIN_LOG("Req Time%s %ld\n",time_buf,tv.tv_usec); if((mrqst->mode & NSP_MRQSTTYPE_MASK) == NSP_MRQSTTYPE_TYPE0) { PRIN_LOG("%s: %d: Received a Type 0 Measurement Request\n", __FUNCTION__, __LINE__); wpc_mgr_proctype0mreq(buf); }else if((mrqst->mode & NSP_MRQSTTYPE_MASK) == NSP_MRQSTTYPE_TYPE1) { PRIN_LOG("%s: %d: Received a Type 1 Measurement Request\n", __FUNCTION__, __LINE__); wpc_mgr_proctype1mreq(buf); } } break; case NSP_SRQST: srqst = (struct nsp_sreq *)(((char *)buf) + NSP_HDR_LEN); if (wpc_debug) { if (wpc_dbg_log_len + WPCDBGHDR_LEN <= WPC_DBG_SIZE) { dump_wpc_log(__LINE__, nsp_header->frame_type); } else { printf("wpc log file is full:cannot written\n"); return; } } else { print_srqst(srqst); } break; case NSP_CRQST: crqst = (struct nsp_cap_req *)(((char *)buf) + NSP_HDR_LEN); if (wpc_debug) { if (wpc_dbg_log_len + WPCDBGHDR_LEN <= WPC_DBG_SIZE) { dump_wpc_log(__LINE__, nsp_header->frame_type); } else { printf("wpc log file is full:cannot written\n"); return; } } else { print_crqst(crqst); } break; case NSP_WAKEUPRQST: wrqst = (struct nsp_wakeup_req *) (((char *)buf) + NSP_HDR_LEN); if (wpc_debug) { if (wpc_dbg_log_len + WPCDBGHDR_LEN <= WPC_DBG_SIZE) { dump_wpc_log(__LINE__, nsp_header->frame_type); } else { printf("wpc log file is full:cannot written\n"); return; } } else { print_wrqst(wrqst); } break; case NSP_TSFRQST: tsfrqst = (struct nsp_tsf_req *) (((char *)buf) + NSP_HDR_LEN); wpc_mgr_proctsfreq(buf); if (wpc_debug) { if (wpc_dbg_log_len + WPCDBGHDR_LEN <= WPC_DBG_SIZE) { dump_wpc_log(__LINE__, nsp_header->frame_type); } else { printf("wpc log file is full:cannot written\n"); return; } } print_tsfrqst(tsfrqst); break; case NSP_STARETURNTOSLEEPREQ: slrqst = (struct nsp_sleep_req *) (((char *)buf) + NSP_HDR_LEN); if (wpc_debug) { if (wpc_dbg_log_len + WPCDBGHDR_LEN <= WPC_DBG_SIZE) { dump_wpc_log(__LINE__, nsp_header->frame_type); } else { printf("wpc log file is full:cannot written\n"); return; } } else { print_slrqst(slrqst); } break; } if(nsp_header->frame_type == NSP_WPCDBGRGST) { wpcdbgrqst = (struct nsp_wpc_dbg_resp *) (((char *)buf) + NSP_HDR_LEN); print_wpcdbgrqst(wpcdbgrqst); if (wpcdbgrqst->dbg_mode) { if( !wpc_debug ) { wpc_debug = 1; fd = write_dbg_log(fd); } } else { if (wpc_debug) { wpc_debug = 0; stop_dbg_log(fd); } } nsp_hdr.SFD = START_OF_FRAME; nsp_hdr.version = NSP_VERSION; nsp_hdr.frame_type = NSP_WPCDBGRESP; nsp_hdr.frame_length = WPCDBGRESP_LEN; memcpy(buf, &nsp_hdr, NSP_HDR_LEN); print_nsp_header(&nsp_hdr); wpcdbgresp.request_id = wpcdbgrqst->request_id; wpcdbgresp.result = 0; memcpy((buf + NSP_HDR_LEN), &wpcdbgresp, WPCDBGRESP_LEN); print_wpcdbgresp(&wpcdbgresp); write_len = NSP_HDR_LEN + WPCDBGRESP_LEN; written = wpc_write(wpc_server_sock, ((char *)buf), write_len); if ( written < write_len) { // TBD : Need to write pending data if there is partial write printf("Partial write closing connection Size: %d Written: %d\n", sizeof(struct nsp_header)+sizeof(struct nsp_mresp), written); wpc_close(wpc_server_sock); FD_CLR(wpc_server_sock, &read_fds); wpc_server_sock = -1; } } else { wpc_nlsendmsg(wpc_driver_sock,nbytes,buf,nlh,&iov,&msg); } } }
static int do_cmd(int cmd, port_addr fd) { switch(cmd) { case 0: { // Identify command // Read the command crc uint32_t ccrc; serial_read(fd, &ccrc, 4); uint32_t eccrc = crc32((void *)0, 0); if(ccrc != eccrc) return send_error_msg(fd, CRC_ERROR); // Set the response length and error code uint32_t resp_length = 12; uint32_t error_code = SUCCESS; // Build the response crc uint32_t crc = crc32_start(); crc = crc32_append(crc, &magic, 4); crc = crc32_append(crc, &resp_length, 4); crc = crc32_append(crc, &error_code, 4); crc = crc32_append(crc, &server_caps, 4); crc = crc32_finish(crc); // Send the response serial_write(fd, &magic, 4); serial_write(fd, &resp_length, 4); serial_write(fd, &error_code, 4); serial_write(fd, &server_caps, 4); serial_write(fd, &crc, 4); fprintf(stderr, "Sent CMD0 response\n"); return 0; } case 1: { // Read directory uint32_t eccrc = crc32_start(); // Read the directory name uint16_t dir_name_len; serial_read(fd, &dir_name_len, 2); eccrc = crc32_append(eccrc, &dir_name_len, 2); char *dir_name = (char *)malloc((int)dir_name_len + 1); memset(dir_name, 0, dir_name_len + 1); serial_read(fd, dir_name, (size_t)dir_name_len); eccrc = crc32_append(eccrc, dir_name, (size_t)dir_name_len); eccrc = crc32_finish(eccrc); // Read the command crc uint32_t ccrc; serial_read(fd, &ccrc, 4); if(ccrc != eccrc) return send_error_msg(fd, CRC_ERROR); // Append the requested dir to the base dir int full_dir_len = strlen(base_dir) + 1 + dir_name_len + 1; char *full_dir = (char *)malloc(full_dir_len); memset(full_dir, 0, full_dir_len); strcat(full_dir, base_dir); strcat(full_dir, "/"); strcat(full_dir, dir_name); // Try and read the requested directory DIR *dirp = opendir(full_dir); if(dirp == NULL) { free(dir_name); free(full_dir); if((errno == ENOENT) || (errno == ENOTDIR)) return send_error_msg(fd, PATH_NOT_FOUND); else return send_error_msg(fd, UNKNOWN_ERROR); } // Count the directory entries int byte_count = 0; uint32_t entry_count = 0; struct dirent *de; while((de = readdir(dirp)) != NULL) { // Add space for byte_size, user_id, group_id // and props fields byte_count += 16; // Add space for name string byte_count += 2; byte_count += strlen(de->d_name); entry_count++; } rewinddir(dirp); // Allocate the buffer to send uint8_t *buf = (uint8_t *)malloc(byte_count); int bptr = 0; // Fill in the buffer uint32_t entries_filled = 0; while((de = readdir(dirp)) != NULL) { // Build a string of the whole filename int fname_len = strlen(de->d_name); int path_len = full_dir_len + 1 + fname_len + 1; char *path = (char *)malloc(path_len); memset(path, 0, path_len); strcat(path, full_dir); strcat(path, "/"); strcat(path, de->d_name); // Get the file stats struct stat stat_buf; if(stat(path, &stat_buf) != 0) { fprintf(stderr, "Error running fstat on %s, errno = %i\n", path, errno); free(path); free(buf); free(full_dir); free(dir_name); return send_error_msg(fd, UNKNOWN_ERROR); } // Fill in the buffer write_word((uint32_t)stat_buf.st_size, buf, bptr); write_word((uint32_t)stat_buf.st_uid, buf, bptr + 4); write_word((uint32_t)stat_buf.st_gid, buf, bptr + 8); write_word((uint32_t)stat_buf.st_mode, buf, bptr + 12); bptr += 16; // Fill in the name write_halfword((uint16_t)dir_name_len, buf, bptr); bptr += 2; memcpy(&buf[bptr], de->d_name, dir_name_len); bptr += dir_name_len; free(path); entries_filled++; } if(entries_filled != entry_count) { // An error has occurred re-parsing the directory fprintf(stderr, "entries_filled (%i) != entry_count (%i)\n", entries_filled, entry_count); free(buf); free(dir_name); free(full_dir); send_error_msg(fd, UNKNOWN_ERROR); } fprintf(stderr, "SERVER: %i directory entries, byte_count %i\n", entry_count, byte_count); // Set the response length and error code uint32_t resp_length = 16 + byte_count; uint32_t error_code = SUCCESS; uint32_t dir_entry_version = 0; // Build the response crc uint32_t crc = crc32_start(); crc = crc32_append(crc, &magic, 4); crc = crc32_append(crc, &resp_length, 4); crc = crc32_append(crc, &error_code, 4); crc = crc32_append(crc, &entry_count, 4); crc = crc32_append(crc, &dir_entry_version, 4); crc = crc32_append(crc, buf, byte_count); crc = crc32_finish(crc); // Send the response serial_write(fd, &magic, 4); serial_write(fd, &resp_length, 4); serial_write(fd, &error_code, 4); serial_write(fd, &entry_count, 4); serial_write(fd, &dir_entry_version, 4); serial_write(fd, buf, byte_count); serial_write(fd, &crc, 4); fprintf(stderr, "Sent CMD1 response\n"); free(buf); free(dir_name); free(full_dir); return 0; } } (void)fd; return 0; }