void server(int port) { int sockfd, new_fd; struct addrinfo hints, *servinfo, *p; struct sockaddr_storage their_addr; socklen_t sin_size; struct sigaction sa; int yes=1; char s[INET6_ADDRSTRLEN]; int rv; int numbytes; char buf[MAXBUFLEN]; char filename[MAXNAMELEN]; uint32_t filename_size; FILE *ft; size_t total; char port_s[100]; char overwrite; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; snprintf(port_s, 100, "%d", port); if ((rv = getaddrinfo(NULL, port_s, &hints, &servinfo)) != 0) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); exit(1); } // loop through all the results and bind to the first we can for(p = servinfo; p != NULL; p = p->ai_next) { if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { perror("server: socket"); continue; } if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { perror("setsockopt"); exit(1); } if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) { close(sockfd); perror("server: bind"); continue; } break; } if (p == NULL) { fprintf(stderr, "server: failed to bind\n"); exit(2); } freeaddrinfo(servinfo); if (listen(sockfd, BACKLOG) == -1) { perror("listen"); exit(1); } sa.sa_handler = sigchld_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; if (sigaction(SIGCHLD, &sa, NULL) == -1) { perror("sigaction"); exit(1); } sin_size = sizeof their_addr; new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size); if (new_fd == -1) { perror("accept"); } inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr), s, sizeof s); printf("Incoming connection from: %s\n", s); numbytes = recv_full(new_fd, &filename_size, sizeof(filename_size)); filename_size = ntohl(filename_size); if (numbytes < sizeof(filename_size)) { printf("Protocol error, exiting.\n"); exit(1); } numbytes = recv_full(new_fd, filename, filename_size); filename[filename_size] = '\0'; if (numbytes < filename_size) { printf("Protocol error, exiting.\n"); exit(1); } if (file_exists(filename)) { printf("%s already exists. Overwrite? Y/n: ", filename); scanf("%c", &overwrite); if (overwrite == 'n') { close(new_fd); close(sockfd); exit(0); } } ft = fopen (filename, "wb"); if (ft == NULL) { perror("Cannon open file"); exit(1); } total = 0; while((numbytes = recv(new_fd, buf, MAXBUFLEN, 0)) > 0) { total += numbytes; printf("\rReceive: %zu", total); fwrite(&buf, 1, numbytes, ft); } printf("\nFile received: %s\n", filename); fclose(ft); close(new_fd); close(sockfd); }
static void handle_request(int sock) { char *buf = NULL; size_t len; json_t *req = NULL, *ret = NULL, *arg; json_error_t json_error; int req_id, err_code = -1; ret = json_object(); if(ret == NULL) goto end; if(recv_full(sock, &len, sizeof(len)) == -1) { log_error_errno(); goto end; } buf = (char *)malloc(len + 1); if(buf == NULL) { log_error_errno(); goto end; } if(recv_full(sock, buf, len) == -1) { log_error_errno(); goto end; } buf[len] = '\0'; enable_listening_fd(sock); req = json_loads(buf, 0, &json_error); if(req == NULL) { log_error(LOG_COLOR_ERROR, "%d: %s", sock, json_error.text); goto end; } if(!json_is_object(req)) goto invalid_request; arg = json_object_get(req, "req_id"); if(arg == NULL || !json_is_integer(arg)) goto invalid_request; req_id = json_integer_value(arg); if(req_id < 0 || req_id >= sizeof(g_req_handler) / sizeof(*g_req_handler)) goto invalid_request; arg = json_object_get(req, "arg"); if(arg == NULL || !json_is_object(arg)) goto invalid_request; err_code = g_req_handler[req_id](arg, ret); end: send_response(sock, err_code, ret); if(req) json_decref(req); if(buf) free(buf); if(ret) json_decref(ret); return; invalid_request: log_error(LOG_COLOR_ERROR, "%d: Invalid request", sock); goto end; }