int32_t send_buf(uint8_t *buf, uint32_t len, Connection *conn, uint8_t flag, uint32_t seq_num) { uint8_t packet[MAX_PACKET_LEN]; int32_t send_len = 0; uint16_t checksum = 0; if (len > 0) { memcpy(&packet[7], buf, len); } seq_num = htonl(seq_num); memcpy(packet, &seq_num, 4); packet[6] = flag; memset(&packet[4], 0, 2); checksum = in_cksum((unsigned short *)packet, len+8); memcpy(&packet[4], &checksum, 2); if ((send_len = sendtoErr(conn->socket_num, packet, len+8, 0, (struct sockaddr *)&conn->remote, conn->len)) < 0) { perror("send_buf:sendto"); exit(1); } // printf("send_buf: len: %u seq: %u flag: %u sum:%u\n", send_len, ntohl(seq_num), flag, checksum); return send_len; }
void srj_connect(srjconn_t *conn) { uint8_t *payload = conn->buffer + sizeof(srjhdr_t); srjhdr_t *hdr = (srjhdr_t *)conn->buffer; size_t packet_len = sizeof(srjconn_t) + 2 * sizeof(uint32_t) + sizeof(uint16_t); hdr->flag = SRJ_FLAG_FNAME; hdr->seq = 0; hdr->cksum = 0; memcpy(payload, &conn->window_size, sizeof(uint32_t)); memcpy(payload + sizeof(uint32_t), &conn->buffer_size, sizeof(uint32_t)); hdr->cksum = in_cksum((unsigned short *)conn->buffer, packet_len); sendtoErr( conn->sk, conn->buffer, packet_len, 0, (struct sockaddr *)&conn->remote, sizeof(struct sockaddr_in) ); }
int32_t send_buf(uint8_t *buf, uint32_t len, Connection *connection, uint8_t flag, uint32_t seq_num, uint8_t *packet) { int32_t send_len = 0; uint16_t checksum = 0; /* set up the packet(seq#, crc, flag, data) */ if (len > 0) memcpy(&packet[7] , buf, len); seq_num = htonl(seq_num); memcpy(&packet[0], &seq_num, 4); packet[6] = flag; memset(&packet[4], 0, 2); checksum = in_cksum((unsigned short *)packet, len + 8); memcpy(&packet[4], &checksum, 2); if ((send_len = sendtoErr(connection->sk_num, packet, len + 8, 0, (struct sockaddr *) &(connection->remote), connection->len)) < 0) { perror("in udp send_buf, sendtoErr"); exit(-1); } return send_len; }
STATE timeout_on_ack(uint8_t * packet, int32_t packet_len) { if(sendtoErr(server.sk_num, packet, packet_len, 0, (struct sockaddr *) &(server.remote), server.len) < 0) { perror("timeout_on_ack sendto"); exit(-1); } return WAIT_ON_ACK; }
Client::State Client::recvPackets() { packet inpkt; packet outpkt; // Check for timeout switch (recvPacket(inpkt)) { case 1: // Receive error. return ERROR; case 2: // Bad checksum or timeout. outpkt = rejpkt(mvSequence); break; default: // if sequence is less than or equal to our own, send RR. Even if it's // lower than it's supposed to be, we'll just send the RR to make the // server feel better about itself. if (inpkt.sequence <= mvSequence) { mvRetries = PKT_TRNSMAX; outpkt = rrpkt(inpkt.sequence); if (inpkt.sequence == mvSequence) { mvSequence++; if (writeTo(inpkt) == 1) { return ERROR; } if (inpkt.type == PKT_TYPE_DAT && inpkt.size < mvBufferSize) { // A valid, less-than-maximum sized packet indicates // end-of-file return DONE; } } } else { // if the sequence is outright wrong, however... std::cout << "Received packet with incorrect sequence. Expected " << mvSequence << " or lower. Received " << inpkt.sequence << std::endl; outpkt = rejpkt(mvSequence); } } // Send response packet if (sendtoErr(mvSocket, &outpkt, sizeof(packet), 0, (sockaddr *)&mvAddr, mvAddrLen) == -1) { std::cerr << "sendto (" << __LINE__ << "): " << strerror(errno) << std::endl; return ERROR; } return RECV_PACKETS; }
void send_pkt(pkt *Pkt, int socket, struct sockaddr_in dst_addr) { int flags = 0; int dst_addr_len = (int)sizeof(dst_addr); if (Pkt != NULL && Pkt->datagram != NULL) { // printf("--Send--\n"); // print_hdr(Pkt); // printf("--------\n"); sendtoErr(socket, Pkt->datagram, Pkt->datagram_len, flags, (struct sockaddr *)&dst_addr, dst_addr_len); } else fprintf(stderr, "send_pkt argument error\n"); }
Client::State Client::init() { // Build packets packet pkt[5]; // connection packet memset(&pkt[0], PKT_TYPE_CXN, sizeof(packet)); pkt[0].checksum = 0; pkt[0].sequence = 0; pkt[0].checksum = in_cksum((unsigned short *)&pkt[0], sizeof(packet)); // 2nd stage connection response memset(&pkt[1], PKT_TYPE_CXN2, sizeof(packet)); pkt[1].sequence = 1; pkt[1].checksum = 0; pkt[1].checksum = in_cksum((unsigned short *)&pkt[1], sizeof(packet)); // buffer size packet memset(&pkt[2], PKT_TYPE_BUF, sizeof(packet)); pkt[2].size = mvBufferSize; pkt[2].sequence = 2; pkt[2].checksum = 0; pkt[2].checksum = in_cksum((unsigned short *)&pkt[2], sizeof(packet)); // window size packet memset(&pkt[3], PKT_TYPE_WIN, sizeof(packet)); pkt[3].size = mvWindowSize; pkt[3].sequence = 3; pkt[3].checksum = 0; pkt[3].checksum = in_cksum((unsigned short *)&pkt[3], sizeof(packet)); // file name packet memset(&pkt[4], PKT_TYPE_FLN, sizeof(packet)); memcpy(pkt[4].data, mvFromName.c_str(), mvFromName.length()+1); pkt[4].data[mvFromName.length()] = '\0'; pkt[4].sequence = 4; pkt[4].checksum = 0; pkt[4].checksum = in_cksum((unsigned short *)&pkt[4], sizeof(packet)); // Send packets int sk; // new socket mvOldSocket = mvSocket; sockaddr_storage addr; for (int i = 0; i < 5 && mvRetries > 0; i++) { packet inpkt; int r; // Send packet if (sendtoErr(mvSocket, &pkt[i], sizeof(packet), 0, (sockaddr *)&mvAddr, mvAddrLen) == -1) { std::cerr << "sendto (" << __LINE__ << "): " << strerror(errno) << std::endl; return ERROR; } // Receive packet if ((r = recvPacket(inpkt)) == 1) { return ERROR; } else if (r == 2) { i--; continue; } mvRetries = PKT_TRNSMAX; // Check for RRs switch (inpkt.type) { case PKT_TYPE_RR: if (inpkt.sequence == i && pkt[i].type == PKT_TYPE_CXN) { mvRemotePort = inpkt.size; // Extract new port number if ((sk = GetSocket(*(sockaddr_in *)&addr)) == -1) { std::cerr << "GetSocket (" << __LINE__ << "): " << strerror(errno) << std::endl; return ERROR; } mvAddrLen = sizeof(mvAddr); } else if (inpkt.sequence == i && pkt[i].type == PKT_TYPE_CXN2) { // Apply new port changes mvSocket = sk; mvAddr = addr; } else if (inpkt.sequence != i) { // Incorrect sequence number: resend packet i--; continue; } break; case PKT_TYPE_REJ: if (inpkt.sequence <= i) { i = inpkt.sequence - 1; } break; } } if (mvRetries <= 0) { return ERROR; } mvSequence = 0; mvRetries = PKT_TRNSMAX; return RECV_PACKETS; }