static int dispatch_msg(int efd, struct epoll_event *ep_event, msg_handler_fn_t msg_handler) { char buf[MAX_BUF_LEN]; struct msg_request_head *head; int fd = ep_event->data.fd; uint32_t event = ep_event->events; /* An error has occured on this fd, or the socket is not ready for reading (why were we notified then?) */ if ((event& EPOLLERR) || (event & EPOLLHUP) || (!(event & EPOLLIN))) { DEBUG_ERROR("error epoll event: %d, err = %d, hup = %d, in = %d\n", event, EPOLLERR, EPOLLHUP, EPOLLIN); epoll_ctl(efd, EPOLL_CTL_ADD, fd, NULL); close(fd); return -1; } if (0 != recv_safe(fd, buf, sizeof(buf))) { response_errno(fd, -1); return -1; } head = (struct msg_request_head *) buf; msg_convert_request_head(head); msg_handler(fd, head->type, head->operation, buf + sizeof(*head)); return 0; }
/** * GET function * Performs the receiving half of a request */ void get(SOCKET s, SOCKADDR_IN sa, char * username, char* filename, int client_num, int server_num, FILE* logfile){ char buffer[FRAME_SIZE]; int count, offset, recv, filesize, size; char tracebuf[128]; FILE* recv_file = fopen(filename, "wb"); if(recv_safe(s, sa, buffer, FRAME_SIZE, 101) == 101){ // Receives the filesize negotiation packet memcpy(&filesize, buffer + (3 * sizeof(char)), sizeof(int)); cout << "Got filesize " << filesize << " starting transfer..." << endl; sprintf(tracebuf, "Filesize %d", filesize); write_log(logfile, username, tracebuf); offset = recv = count = 0; int expected_size = WINDOW_SIZE + 1; int recv_count, nak; int next = 0; int packet_id; // Receive the file while(1){ nak = -1; recv_count = 0; next = offset; while(count < filesize && recv_count < WINDOW_SIZE){ if(filesize - count >= (FRAME_SIZE)) size = (FRAME_SIZE / sizeof(char)); // Read the full buffer else size = ((filesize - count) / sizeof(char)); // Read a subset of the buffer if((packet_id = recv_packet(s,sa,buffer,FRAME_SIZE,offset)) == offset){ // Receive the packet from the peer count += FRAME_SIZE; fwrite(buffer,sizeof(char),size,recv_file); // Write to the output file sprintf(tracebuf, "Recv %d (%d of %d)", offset, count, filesize); write_log(logfile, username, tracebuf); offset = (offset + 1) % expected_size; recv_count++; }else if(packet_id < 0){ nak = offset; break; }else if(packet_id == 101){ fclose(recv_file); return get(s, sa, username, filename, client_num, server_num, logfile); } } while(recv_count > 0 || nak >= 0){ memset(buffer,0,FRAME_SIZE); if(next != nak) strncpy(buffer, "ACK", 3); // Send ACK else strncpy(buffer, "NAK", 3); // Send NAK send_packet(s,sa,buffer,FRAME_SIZE,next); // Send acknowledgement recv_count--; if(next == nak){ offset = nak; sprintf(tracebuf, "Sent NAK for %d", nak); write_log(logfile, username, tracebuf); break; } // As soon as we send a NAK we can break next = (next + 1) % expected_size; } if(count >= filesize) break; } strncpy(buffer, "ALL", 3); send_packet(s, sa, buffer, FRAME_SIZE, next); cout << "Transfer completed! " << count << " bytes received" << endl; fclose(recv_file); }else{ fclose(recv_file); return get(s, sa, username, filename, client_num, server_num, logfile); } }
static int dgram_process (int sock, StunAgent *oldagent, StunAgent *newagent) { struct sockaddr_storage addr; uint8_t buf[STUN_MAX_MESSAGE_SIZE]; char ctlbuf[CMSG_SPACE (sizeof (struct in6_pktinfo))]; struct iovec iov = { buf, sizeof (buf) }; StunMessage request; StunMessage response; StunValidationStatus validation; StunAgent *agent = NULL; struct msghdr mh = { .msg_name = (struct sockaddr *)&addr, .msg_namelen = sizeof (addr), .msg_iov = &iov, .msg_iovlen = 1, .msg_control = ctlbuf, .msg_controllen = sizeof (ctlbuf) }; size_t len = recv_safe (sock, &mh); if (len == (size_t)-1) return -1; validation = stun_agent_validate (newagent, &request, buf, len, NULL, 0); if (validation == STUN_VALIDATION_SUCCESS) { agent = newagent; } else { validation = stun_agent_validate (oldagent, &request, buf, len, NULL, 0); agent = oldagent; } /* Unknown attributes */ if (validation == STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE) { stun_agent_build_unknown_attributes_error (agent, &response, buf, sizeof (buf), &request); goto send_buf; } /* Mal-formatted packets */ if (validation != STUN_VALIDATION_SUCCESS || stun_message_get_class (&request) != STUN_REQUEST) { return -1; } switch (stun_message_get_method (&request)) { case STUN_BINDING: stun_agent_init_response (agent, &response, buf, sizeof (buf), &request); if (stun_message_has_cookie (&request)) stun_message_append_xor_addr (&response, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, mh.msg_name, mh.msg_namelen); else stun_message_append_addr (&response, STUN_ATTRIBUTE_MAPPED_ADDRESS, mh.msg_name, mh.msg_namelen); break; default: stun_agent_init_error (agent, &response, buf, sizeof (buf), &request, STUN_ERROR_BAD_REQUEST); } iov.iov_len = stun_agent_finish_message (agent, &response, NULL, 0); send_buf: len = send_safe (sock, &mh); return (len < iov.iov_len) ? -1 : 0; } static int run (int family, int protocol, unsigned port) { StunAgent oldagent; StunAgent newagent; int sock = listen_socket (family, SOCK_DGRAM, protocol, port); if (sock == -1) return -1; stun_agent_init (&oldagent, known_attributes, STUN_COMPATIBILITY_RFC3489, 0); stun_agent_init (&newagent, known_attributes, STUN_COMPATIBILITY_RFC5389, STUN_AGENT_USAGE_USE_FINGERPRINT); for (;;) dgram_process (sock, &oldagent, &newagent); }