uint8_t bb_i2c_write( uint8_t addr, uint8_t *buf, uint8_t len ) { uint8_t rc = 0; bb_start(); bb_out( addr ); // address + W if ( get_ack() ) { while ( len > 0 ) { bb_out( *buf++ ); if ( get_ack() == 0 ) { rc = 1; break; } len--; } } else { rc = 1; } bb_stop(); return rc; }
uint8_t bb_i2c_read( uint8_t addr, uint8_t *buf, uint8_t len ) { uint8_t rc = 0; bb_start(); bb_out( addr | 0x01 ); // address + R if ( get_ack() ) { while ( len > 0 ) { *buf++ = bb_in(); len--; if ( len > 0 ) { send_ack(); } else { send_nak(); } } } else { rc = 1; } bb_stop(); return rc; }
void Handle (DHT& dht, const Host& host, const Packet& pckt) { Key k = pckt.GetArg<Key>(DHT_GET_KEY); pf_log[W_DHT] << "Get received with key " << k; if(dht.GetStorage()->hasKey(k)) { pf_log[W_DHT] << "Answer with data " << dht.GetStorage()->getInfo(k)->GetStr(); Packet get_ack(DHTGetAckType, dht.GetMe(), host.GetKey()); get_ack.SetArg(DHT_GET_ACK_KEY, k); get_ack.SetArg(DHT_GET_ACK_DATA, dht.GetStorage()->getInfo(k)); if(!dht.GetChimera()->Send(host, get_ack)) pf_log[W_DHT] << "Send get ACK message failed!"; return; } pf_log[W_DHT] << "Data not in cache, try to relay to a closest host."; if(!dht.GetChimera()->Route(pckt)) { pf_log[W_DHT] << "I'm the owner and the key is unknow, answer with GET_NACK."; Packet get_nack(DHTGetNAckType, dht.GetMe(), host.GetKey()); get_nack.SetArg(DHT_GET_NACK_KEY, k); if(!dht.GetChimera()->Send(host, get_nack)) pf_log[W_DHT] << "Send get NACK message failed!"; return; } pf_log[W_DHT] << "GET relayed."; }
/** * handle packet loss case (timeout) * @param dl */ static void dl_loss(download_t *dl) { int i ; for (i = 0; i < LOSS_ACK_NUM; i++) { send_ack(dl->p_index, get_ack(dl)); } dl->ts = get_timestamp_now(); dl->block_update = 1; }
static int send_acked ( char *str ) { if ( scanfd < 0 ) return -1; while ( *str ) { if ( write ( scanfd, str++, 1 ) != 1 || get_ack () < 0 ) return -1; } return 0; }
/* * jx100_reset * Send a CAN character to the scanner to get it to reset. This can * be useful for aborting a scan. One caveat is that the scanner * resets its baud rate to 9600. * It turns out that the scanner won't listen all of the time, and * will even send some characters after being requested to reset. Sigh. */ int jx100_reset () { if ( status ) (*status) ( "resetting scanner" ); scanlines = 0; if ( send ( "\x18" ) < 0 ) /* request a reset... */ return -1; msleep ( 1000 ); if ( send ( "\x18" ) < 0 ) /* ...and then request again */ return -1; if ( cfgetispeed ( &tt ) != B9600 ) { /* reset to 9600 */ cfsetispeed ( &tt, B9600 ); cfsetospeed ( &tt, B9600 ); if ( tcsetattr ( scanfd, TCSANOW, &tt ) < 0 ) return -1; #ifdef linux /* reset meaning of 38400 */ (void) ioctl ( scanfd, TIOCGSERIAL, &serial ); serial.flags &= ~ASYNC_SPD_MASK; (void) ioctl ( scanfd, TIOCSSERIAL, &serial ); #endif } /* we wait a bit, then discard any spurious characters that came in */ msleep ( 1000 ); if ( tcflush ( scanfd, TCIFLUSH ) < 0 ) return -1; /* physical head movement during reset can take 3 - 10 seconds */ timeout = 10000; if ( get_ack() == 0 ) /* got ack, good! */ return 0; /* We didn't get an ack. Wait a bit, discard chars, try again */ msleep ( 1000 ); if ( tcflush ( scanfd, TCIFLUSH ) < 0 ) return -1; timeout = 10000; /* If we don't get it this time, give up */ return get_ack (); }
/* Main sender function. Taken from the state diagram on slide 6, chapter 5 */ void sender(int window, int timeout) { int base = 1; int nextseqnum = 1; bool allsent = false; PQueue sendQ; pqueue_init(&sendQ, window); while ( !(allsent && pqueue_empty(&sendQ)) ) { int acknum = -1; /* Send new data */ if (!allsent && nextseqnum < base + window) { Packet* packet = add_packet(&sendQ, nextseqnum); if (packet == NULL) { allsent = true; } else { send_packet(packet); if (base == nextseqnum) start_timer(timeout); nextseqnum++; } } /* Attempt to receive an ACK. */ acknum = get_ack(0); if (acknum > 0) { base = acknum + 1; if (base == nextseqnum) stop_timer(); else start_timer(timeout); } /* Clean up the queue */ while (!pqueue_empty(&sendQ) && pqueue_head(&sendQ)->seqn < base) { pqueue_pop(&sendQ); } /* Handle timeouts */ if (cnt_active && cnt_time >= cnt_timeout) { start_timer(cnt_timeout); pqueue_map(&sendQ, &send_packet); } pqueue_debug_print(&sendQ); } pqueue_destroy(&sendQ); }
/** * receive the packet, save it into buffer * send corresponding ack back * @param dl, the handler * @param pkt, the received packet * @return 0 on success, -1 if fails */ int dl_recv(download_t *dl, packet_t *pkt) { uint32_t seq; size_t offset; if (dl->finished) { return 0; } /* do not update rtt until start */ if (dl->started && !dl->block_update) { update_rtt(&dl->rtt, &dl->dev, dl->ts); } else { /* record data_len for the first time */ dl->data_length = GET_DATA_LEN(pkt); dl->started = 1; dl->block_update = 0; } seq = GET_SEQ(pkt); offset = (seq - 1) * dl->data_length ; // discard data packet with seq number not sitting in current receive window // or size exceeds the buffer length. if( ! seq_fit_in(&dl->rwin, seq) || offset + GET_DATA_LEN(pkt) > BT_CHUNK_SIZE){ return -1; } if(! seq_exist_in(&dl->rwin, seq)){ memcpy(dl->buffer + offset, GET_DATA(pkt), GET_DATA_LEN(pkt)); recvwin_mark(&dl->rwin, seq); } send_ack(dl->p_index, get_ack(dl)); dl->ts = get_timestamp_now(); dl->timeout_cnt = 0; if ( (dl->next_pkt_expected -1)* dl->data_length >= BT_CHUNK_SIZE) { dl->finished = 1; } return 0; }
static inline void treat_aknowledgment(edcl_packet_t* packet, unsigned int* offset, unsigned int* size, unsigned int* sequence, unsigned int* nb_ack) { /* We've been aknowledge, keep sending */ if (get_ack(packet->header)) { *offset += min(*size, MAX_DATA_SIZE); *size -= min(*size, MAX_DATA_SIZE); ++(*sequence); ++(*nb_ack); } /* The sequence number was wrong, fix it */ else { if (config.verbose) fprintf(stderr, " Wrong sequence number (%d) should be: %d.\n", *sequence, get_sequence(packet->header)); *sequence = get_sequence(packet->header); } }
/* Description: Recieve a packet and send it. * Author: Albin Severinson * Date: 03/03/15 */ int send_packet(bstring packet) { int rc = 0; int i = 0; int j = 0; char byte = 0; debug("[SENDING]: %s", bdata(packet)); //Store packet size int data_size = blength(packet); for(j = 0;j < MAX_PACKET_RESEND;j++){ debug("[SENDING PACKET] size: %d try: %d", data_size, j); //Transmit one byte at a time for(i = 0;i < data_size;i++){ byte = bchar(packet, i); send_byte(byte); //debug("Sent [%d = %d]", i, byte); } //Wait for ACK frame if(data_size != 1){ rc = get_ack(); //Return if we got the ACK if(rc == 0){ bdestroy(packet); return 0; } } } bdestroy(packet); return -1; }
static int find_common(struct fetch_negotiator *negotiator, struct fetch_pack_args *args, int fd[2], struct object_id *result_oid, struct ref *refs) { int fetching; int count = 0, flushes = 0, flush_at = INITIAL_FLUSH, retval; const struct object_id *oid; unsigned in_vain = 0; int got_continue = 0; int got_ready = 0; struct strbuf req_buf = STRBUF_INIT; size_t state_len = 0; if (args->stateless_rpc && multi_ack == 1) die(_("--stateless-rpc requires multi_ack_detailed")); if (!args->no_dependents) { mark_tips(negotiator, args->negotiation_tips); for_each_cached_alternate(negotiator, insert_one_alternate_object); } fetching = 0; for ( ; refs ; refs = refs->next) { struct object_id *remote = &refs->old_oid; const char *remote_hex; struct object *o; /* * If that object is complete (i.e. it is an ancestor of a * local ref), we tell them we have it but do not have to * tell them about its ancestors, which they already know * about. * * We use lookup_object here because we are only * interested in the case we *know* the object is * reachable and we have already scanned it. * * Do this only if args->no_dependents is false (if it is true, * we cannot trust the object flags). */ if (!args->no_dependents && ((o = lookup_object(the_repository, remote->hash)) != NULL) && (o->flags & COMPLETE)) { continue; } remote_hex = oid_to_hex(remote); if (!fetching) { struct strbuf c = STRBUF_INIT; if (multi_ack == 2) strbuf_addstr(&c, " multi_ack_detailed"); if (multi_ack == 1) strbuf_addstr(&c, " multi_ack"); if (no_done) strbuf_addstr(&c, " no-done"); if (use_sideband == 2) strbuf_addstr(&c, " side-band-64k"); if (use_sideband == 1) strbuf_addstr(&c, " side-band"); if (args->deepen_relative) strbuf_addstr(&c, " deepen-relative"); if (args->use_thin_pack) strbuf_addstr(&c, " thin-pack"); if (args->no_progress) strbuf_addstr(&c, " no-progress"); if (args->include_tag) strbuf_addstr(&c, " include-tag"); if (prefer_ofs_delta) strbuf_addstr(&c, " ofs-delta"); if (deepen_since_ok) strbuf_addstr(&c, " deepen-since"); if (deepen_not_ok) strbuf_addstr(&c, " deepen-not"); if (agent_supported) strbuf_addf(&c, " agent=%s", git_user_agent_sanitized()); if (args->filter_options.choice) strbuf_addstr(&c, " filter"); packet_buf_write(&req_buf, "want %s%s\n", remote_hex, c.buf); strbuf_release(&c); } else packet_buf_write(&req_buf, "want %s\n", remote_hex); fetching++; } if (!fetching) { strbuf_release(&req_buf); packet_flush(fd[1]); return 1; } if (is_repository_shallow(the_repository)) write_shallow_commits(&req_buf, 1, NULL); if (args->depth > 0) packet_buf_write(&req_buf, "deepen %d", args->depth); if (args->deepen_since) { timestamp_t max_age = approxidate(args->deepen_since); packet_buf_write(&req_buf, "deepen-since %"PRItime, max_age); } if (args->deepen_not) { int i; for (i = 0; i < args->deepen_not->nr; i++) { struct string_list_item *s = args->deepen_not->items + i; packet_buf_write(&req_buf, "deepen-not %s", s->string); } } if (server_supports_filtering && args->filter_options.choice) packet_buf_write(&req_buf, "filter %s", args->filter_options.filter_spec); packet_buf_flush(&req_buf); state_len = req_buf.len; if (args->deepen) { char *line; const char *arg; struct object_id oid; send_request(args, fd[1], &req_buf); while ((line = packet_read_line(fd[0], NULL))) { if (skip_prefix(line, "shallow ", &arg)) { if (get_oid_hex(arg, &oid)) die(_("invalid shallow line: %s"), line); register_shallow(the_repository, &oid); continue; } if (skip_prefix(line, "unshallow ", &arg)) { if (get_oid_hex(arg, &oid)) die(_("invalid unshallow line: %s"), line); if (!lookup_object(the_repository, oid.hash)) die(_("object not found: %s"), line); /* make sure that it is parsed as shallow */ if (!parse_object(the_repository, &oid)) die(_("error in object: %s"), line); if (unregister_shallow(&oid)) die(_("no shallow found: %s"), line); continue; } die(_("expected shallow/unshallow, got %s"), line); } } else if (!args->stateless_rpc) send_request(args, fd[1], &req_buf); if (!args->stateless_rpc) { /* If we aren't using the stateless-rpc interface * we don't need to retain the headers. */ strbuf_setlen(&req_buf, 0); state_len = 0; } flushes = 0; retval = -1; if (args->no_dependents) goto done; while ((oid = negotiator->next(negotiator))) { packet_buf_write(&req_buf, "have %s\n", oid_to_hex(oid)); print_verbose(args, "have %s", oid_to_hex(oid)); in_vain++; if (flush_at <= ++count) { int ack; packet_buf_flush(&req_buf); send_request(args, fd[1], &req_buf); strbuf_setlen(&req_buf, state_len); flushes++; flush_at = next_flush(args->stateless_rpc, count); /* * We keep one window "ahead" of the other side, and * will wait for an ACK only on the next one */ if (!args->stateless_rpc && count == INITIAL_FLUSH) continue; consume_shallow_list(args, fd[0]); do { ack = get_ack(fd[0], result_oid); if (ack) print_verbose(args, _("got %s %d %s"), "ack", ack, oid_to_hex(result_oid)); switch (ack) { case ACK: flushes = 0; multi_ack = 0; retval = 0; goto done; case ACK_common: case ACK_ready: case ACK_continue: { struct commit *commit = lookup_commit(the_repository, result_oid); int was_common; if (!commit) die(_("invalid commit %s"), oid_to_hex(result_oid)); was_common = negotiator->ack(negotiator, commit); if (args->stateless_rpc && ack == ACK_common && !was_common) { /* We need to replay the have for this object * on the next RPC request so the peer knows * it is in common with us. */ const char *hex = oid_to_hex(result_oid); packet_buf_write(&req_buf, "have %s\n", hex); state_len = req_buf.len; /* * Reset in_vain because an ack * for this commit has not been * seen. */ in_vain = 0; } else if (!args->stateless_rpc || ack != ACK_common) in_vain = 0; retval = 0; got_continue = 1; if (ack == ACK_ready) got_ready = 1; break; } } } while (ack); flushes--; if (got_continue && MAX_IN_VAIN < in_vain) { print_verbose(args, _("giving up")); break; /* give up */ } if (got_ready) break; } } done: if (!got_ready || !no_done) { packet_buf_write(&req_buf, "done\n"); send_request(args, fd[1], &req_buf); } print_verbose(args, _("done")); if (retval != 0) { multi_ack = 0; flushes++; } strbuf_release(&req_buf); if (!got_ready || !no_done) consume_shallow_list(args, fd[0]); while (flushes || multi_ack) { int ack = get_ack(fd[0], result_oid); if (ack) { print_verbose(args, _("got %s (%d) %s"), "ack", ack, oid_to_hex(result_oid)); if (ack == ACK) return 0; multi_ack = 1; continue; } flushes--; } /* it is no error to fetch into a completely empty repo */ return count ? retval : 0; }
static int find_common(int fd[2], unsigned char *result_sha1, struct ref *refs) { int fetching; int count = 0, flushes = 0, retval; const unsigned char *sha1; unsigned in_vain = 0; int got_continue = 0; if (marked) for_each_ref(clear_marks, NULL); marked = 1; for_each_ref(rev_list_insert_ref, NULL); fetching = 0; for ( ; refs ; refs = refs->next) { unsigned char *remote = refs->old_sha1; struct object *o; /* * If that object is complete (i.e. it is an ancestor of a * local ref), we tell them we have it but do not have to * tell them about its ancestors, which they already know * about. * * We use lookup_object here because we are only * interested in the case we *know* the object is * reachable and we have already scanned it. */ if (((o = lookup_object(remote)) != NULL) && (o->flags & COMPLETE)) { continue; } if (!fetching) packet_write(fd[1], "want %s%s%s%s%s%s%s%s\n", sha1_to_hex(remote), (multi_ack ? " multi_ack" : ""), (use_sideband == 2 ? " side-band-64k" : ""), (use_sideband == 1 ? " side-band" : ""), (args.use_thin_pack ? " thin-pack" : ""), (args.no_progress ? " no-progress" : ""), (args.include_tag ? " include-tag" : ""), " ofs-delta"); else packet_write(fd[1], "want %s\n", sha1_to_hex(remote)); fetching++; } if (is_repository_shallow()) write_shallow_commits(fd[1], 1); if (args.depth > 0) packet_write(fd[1], "deepen %d", args.depth); packet_flush(fd[1]); if (!fetching) return 1; if (args.depth > 0) { char line[1024]; unsigned char sha1[20]; while (packet_read_line(fd[0], line, sizeof(line))) { if (!prefixcmp(line, "shallow ")) { if (get_sha1_hex(line + 8, sha1)) die("invalid shallow line: %s", line); register_shallow(sha1); continue; } if (!prefixcmp(line, "unshallow ")) { if (get_sha1_hex(line + 10, sha1)) die("invalid unshallow line: %s", line); if (!lookup_object(sha1)) die("object not found: %s", line); /* make sure that it is parsed as shallow */ if (!parse_object(sha1)) die("error in object: %s", line); if (unregister_shallow(sha1)) die("no shallow found: %s", line); continue; } die("expected shallow/unshallow, got %s", line); } } flushes = 0; retval = -1; while ((sha1 = get_rev())) { packet_write(fd[1], "have %s\n", sha1_to_hex(sha1)); if (args.verbose) fprintf(stderr, "have %s\n", sha1_to_hex(sha1)); in_vain++; if (!(31 & ++count)) { int ack; packet_flush(fd[1]); flushes++; /* * We keep one window "ahead" of the other side, and * will wait for an ACK only on the next one */ if (count == 32) continue; do { ack = get_ack(fd[0], result_sha1); if (args.verbose && ack) fprintf(stderr, "got ack %d %s\n", ack, sha1_to_hex(result_sha1)); if (ack == 1) { flushes = 0; multi_ack = 0; retval = 0; goto done; } else if (ack == 2) { struct commit *commit = lookup_commit(result_sha1); mark_common(commit, 0, 1); retval = 0; in_vain = 0; got_continue = 1; } } while (ack); flushes--; if (got_continue && MAX_IN_VAIN < in_vain) { if (args.verbose) fprintf(stderr, "giving up\n"); break; /* give up */ } } } done: packet_write(fd[1], "done\n"); if (args.verbose) fprintf(stderr, "done\n"); if (retval != 0) { multi_ack = 0; flushes++; } while (flushes || multi_ack) { int ack = get_ack(fd[0], result_sha1); if (ack) { if (args.verbose) fprintf(stderr, "got ack (%d) %s\n", ack, sha1_to_hex(result_sha1)); if (ack == 1) return 0; multi_ack = 1; continue; } flushes--; } /* it is no error to fetch into a completely empty repo */ return count ? retval : 0; }
/** * Send an edcl packet and fragment it if max_packet_size < data_size */ static int send_fragmented(void) { unsigned int nb_ack_packet = 0; unsigned int address_offset = 0; unsigned int nb_sent_packet = 0; unsigned int local_data_size = config.data_size; edcl_packet_t* packet = NULL; /* Allocating the packet of the packet */ packet = calloc(1, min(local_data_size, MAX_DATA_SIZE) + sizeof (edcl_header_t)); if (packet == NULL) goto error_malloc; do { /* Filling up the edcl header */ clear_header(packet->header); set_operation(packet->header, WRITE_OP); set_sequence(packet->header, config.sequence_number); set_address(packet->header, config.memory_address + address_offset); set_length(packet->header, min(local_data_size, MAX_DATA_SIZE)); if (config.verbose) fprintf(stderr, " [%d] Trying to write at 0x%08x.", config.sequence_number, config.memory_address + address_offset); /* Copying the data in the packet */ memcpy(packet->data, config.data_c + address_offset, min(local_data_size, MAX_DATA_SIZE)); /* Sending the packet to the ethernet IP */ if (sendto(config.socket, packet, min(local_data_size, MAX_DATA_SIZE) + sizeof (edcl_header_t), 0, config.serv_info->ai_addr, config.serv_info->ai_addrlen) == -1) goto error_send; /* Waiting for the aknowledgment */ if (recvfrom(config.socket, packet, sizeof (edcl_header_t) + min(local_data_size, MAX_DATA_SIZE), 0, NULL, 0) == -1) goto error_recvfrom; /* We've been aknowledge, keep sending */ if (get_ack(packet->header)) { if (config.verbose) fprintf(stderr, "\t[OK]\n"); address_offset += min(local_data_size, MAX_DATA_SIZE); local_data_size -= min(local_data_size, MAX_DATA_SIZE); ++config.sequence_number; ++nb_ack_packet; } /* The sequence number was wrong, fix it */ else { if (config.verbose) fprintf(stderr, "\t[Failed]\n Wrong sequence number (%d) should be: %d. Fixed.\n", config.sequence_number, get_sequence(packet->header)); config.sequence_number = get_sequence(packet->header); } ++nb_sent_packet; } while (local_data_size > 0); if (config.verbose) { fprintf(stderr, "The datas have been fragmented in %d packets.\n", nb_ack_packet); fprintf(stderr, "\t %d packets have been sent (%d have been lost).\n", nb_sent_packet, nb_sent_packet - nb_ack_packet); } /* Releasing ressources */ free(packet); return (0); error_recvfrom: error_send: if (config.verbose) fprintf(stderr, "Error while sending the packet.\n"); free(packet); return (errno); error_malloc: if (config.verbose) fprintf(stderr, "Unable to allocate the packet.\n"); return (errno); }
void rwqAction(int sockID, struct sockaddr_in sockInfo, struct PARAMS *params) { unsigned short int bnum = 1; unsigned short int sz = 0; tftp_ack_hdr ack; tftp_rwq_hdr rwq; tftp_data_hdr data; char buffer[MAX_BUFFER]; bzero(&data, sizeof(tftp_data_hdr)); bzero(&rwq, sizeof(tftp_rwq_hdr)); rwq_deserialize(&rwq, buffer); if(mode_transfer(rwq.mode, "octet", params) == -1) { sendError(sockID, sockInfo, RFC1350_OP_ERROR, RFC1350_ERR_NOTDEF, "Set transfer mode to octet"); return; } FILE *pFile = NULL; if((pFile = open_file(rwq.filename, "rb", params)) == NULL) { return; } if(timeout_option(&rwq, params) == 1) { sendACKOpt(sockID, sockInfo, "timeout", params->rexmt); } int t_out = 0; int intents = 5; do { bzero(buffer, MAX_BUFFER); bzero(&data, sizeof(tftp_data_hdr)); data.opcode = RFC1350_OP_DATA; data.num_block = bnum++; sz = fread(data.data, 1, RFC1350_BLOCKSIZE, pFile); sz = data_serialize(&data, buffer, sz); bzero(&ack, sizeof(tftp_ack_hdr)); intents = 5; do { sendInfo(sockID, sockInfo, buffer, sz); if((t_out = select_func(sockID, params->rexmt)) == 1) { get_ack(&ack, sockID, sockInfo, params); ack_serialize(&ack, buffer); } }while(t_out == 0 && --intents); }while((sz - SHORT_SIZE * 2) == RFC1350_BLOCKSIZE && t_out != -1); if(intents == 0) { printf("Transfer timed out\n"); } fclose(pFile); }
/** * * @param fd * The netlink socket fd * @param type * The type of netlink message * @param data * The data to send * @param size * The length of the data in bytes * @return * This function returns a positive sequence number on success, else -errno. */ static int audit_send(int fd, int type, const void* data, size_t size) { int rc; static int16_t sequence = 0; struct audit_message req; struct sockaddr_nl addr; memset(&req, 0, sizeof(req)); memset(&addr, 0, sizeof(addr)); /* We always send netlink messaged */ addr.nl_family = AF_NETLINK; /* Set up the netlink headers */ req.nlh.nlmsg_type = type; req.nlh.nlmsg_len = NLMSG_SPACE(size); req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; /* * Check for a valid fd, even though sendto would catch this, its easier * to always blindly increment the sequence number */ if (fd < 0) { return -EBADF; } /* Ensure the message is not too big */ if (NLMSG_SPACE(size) > MAX_AUDIT_MESSAGE_LENGTH) { return -EINVAL; } /* Only memcpy in the data if it was specified */ if (size && data) { memcpy(NLMSG_DATA(&req.nlh), data, size); } /* * Only increment the sequence number on a guarantee * you will send it to the kernel. * * Also, the sequence is defined as a u32 in the kernel * struct. Using an int here might not work on 32/64 bit splits. A * signed 64 bit value can overflow a u32..but a u32 * might not fit in the response, so we need to use s32. * Which is still kind of hackish since int could be 16 bits * in size. The only safe type to use here is a signed 16 * bit value. */ req.nlh.nlmsg_seq = ++sequence; /* While failing and its due to interrupts */ rc = TEMP_FAILURE_RETRY(sendto(fd, &req, req.nlh.nlmsg_len, 0, (struct sockaddr*)&addr, sizeof(addr))); /* Not all the bytes were sent */ if (rc < 0) { rc = -errno; goto out; } else if ((uint32_t)rc != req.nlh.nlmsg_len) { rc = -EPROTO; goto out; } /* We sent all the bytes, get the ack */ rc = get_ack(fd); /* If the ack failed, return the error, else return the sequence number */ rc = (rc == 0) ? (int)sequence : rc; out: /* Don't let sequence roll to negative */ if (sequence < 0) { sequence = 0; } return rc; }
static int find_common(struct fetch_pack_args *args, int fd[2], unsigned char *result_sha1, struct ref *refs) { int fetching; int count = 0, flushes = 0, flush_at = INITIAL_FLUSH, retval; const unsigned char *sha1; unsigned in_vain = 0; int got_continue = 0; int got_ready = 0; struct strbuf req_buf = STRBUF_INIT; size_t state_len = 0; if (args->stateless_rpc && multi_ack == 1) die("--stateless-rpc requires multi_ack_detailed"); if (marked) for_each_ref(clear_marks, NULL); marked = 1; for_each_ref(rev_list_insert_ref, NULL); for_each_alternate_ref(insert_one_alternate_ref, NULL); fetching = 0; for ( ; refs ; refs = refs->next) { unsigned char *remote = refs->old_sha1; const char *remote_hex; struct object *o; /* * If that object is complete (i.e. it is an ancestor of a * local ref), we tell them we have it but do not have to * tell them about its ancestors, which they already know * about. * * We use lookup_object here because we are only * interested in the case we *know* the object is * reachable and we have already scanned it. */ if (((o = lookup_object(remote)) != NULL) && (o->flags & COMPLETE)) { continue; } remote_hex = sha1_to_hex(remote); if (!fetching) { struct strbuf c = STRBUF_INIT; if (multi_ack == 2) strbuf_addstr(&c, " multi_ack_detailed"); if (multi_ack == 1) strbuf_addstr(&c, " multi_ack"); if (no_done) strbuf_addstr(&c, " no-done"); if (use_sideband == 2) strbuf_addstr(&c, " side-band-64k"); if (use_sideband == 1) strbuf_addstr(&c, " side-band"); if (args->use_thin_pack) strbuf_addstr(&c, " thin-pack"); if (args->no_progress) strbuf_addstr(&c, " no-progress"); if (args->include_tag) strbuf_addstr(&c, " include-tag"); if (prefer_ofs_delta) strbuf_addstr(&c, " ofs-delta"); if (agent_supported) strbuf_addf(&c, " agent=%s", git_user_agent_sanitized()); packet_buf_write(&req_buf, "want %s%s\n", remote_hex, c.buf); strbuf_release(&c); } else packet_buf_write(&req_buf, "want %s\n", remote_hex); fetching++; } if (!fetching) { strbuf_release(&req_buf); packet_flush(fd[1]); return 1; } if (is_repository_shallow()) write_shallow_commits(&req_buf, 1, NULL); if (args->depth > 0) packet_buf_write(&req_buf, "deepen %d", args->depth); packet_buf_flush(&req_buf); state_len = req_buf.len; if (args->depth > 0) { char *line; const char *arg; unsigned char sha1[20]; send_request(args, fd[1], &req_buf); while ((line = packet_read_line(fd[0], NULL))) { if (skip_prefix(line, "shallow ", &arg)) { if (get_sha1_hex(arg, sha1)) die("invalid shallow line: %s", line); register_shallow(sha1); continue; } if (skip_prefix(line, "unshallow ", &arg)) { if (get_sha1_hex(arg, sha1)) die("invalid unshallow line: %s", line); if (!lookup_object(sha1)) die("object not found: %s", line); /* make sure that it is parsed as shallow */ if (!parse_object(sha1)) die("error in object: %s", line); if (unregister_shallow(sha1)) die("no shallow found: %s", line); continue; } die("expected shallow/unshallow, got %s", line); } } else if (!args->stateless_rpc) send_request(args, fd[1], &req_buf); if (!args->stateless_rpc) { /* If we aren't using the stateless-rpc interface * we don't need to retain the headers. */ strbuf_setlen(&req_buf, 0); state_len = 0; } flushes = 0; retval = -1; while ((sha1 = get_rev())) { packet_buf_write(&req_buf, "have %s\n", sha1_to_hex(sha1)); if (args->verbose) fprintf(stderr, "have %s\n", sha1_to_hex(sha1)); in_vain++; if (flush_at <= ++count) { int ack; packet_buf_flush(&req_buf); send_request(args, fd[1], &req_buf); strbuf_setlen(&req_buf, state_len); flushes++; flush_at = next_flush(args, count); /* * We keep one window "ahead" of the other side, and * will wait for an ACK only on the next one */ if (!args->stateless_rpc && count == INITIAL_FLUSH) continue; consume_shallow_list(args, fd[0]); do { ack = get_ack(fd[0], result_sha1); if (args->verbose && ack) fprintf(stderr, "got ack %d %s\n", ack, sha1_to_hex(result_sha1)); switch (ack) { case ACK: flushes = 0; multi_ack = 0; retval = 0; goto done; case ACK_common: case ACK_ready: case ACK_continue: { struct commit *commit = lookup_commit(result_sha1); if (!commit) die("invalid commit %s", sha1_to_hex(result_sha1)); if (args->stateless_rpc && ack == ACK_common && !(commit->object.flags & COMMON)) { /* We need to replay the have for this object * on the next RPC request so the peer knows * it is in common with us. */ const char *hex = sha1_to_hex(result_sha1); packet_buf_write(&req_buf, "have %s\n", hex); state_len = req_buf.len; } mark_common(commit, 0, 1); retval = 0; in_vain = 0; got_continue = 1; if (ack == ACK_ready) { clear_prio_queue(&rev_list); got_ready = 1; } break; } } } while (ack); flushes--; if (got_continue && MAX_IN_VAIN < in_vain) { if (args->verbose) fprintf(stderr, "giving up\n"); break; /* give up */ } } } done: if (!got_ready || !no_done) { packet_buf_write(&req_buf, "done\n"); send_request(args, fd[1], &req_buf); } if (args->verbose) fprintf(stderr, "done\n"); if (retval != 0) { multi_ack = 0; flushes++; } strbuf_release(&req_buf); if (!got_ready || !no_done) consume_shallow_list(args, fd[0]); while (flushes || multi_ack) { int ack = get_ack(fd[0], result_sha1); if (ack) { if (args->verbose) fprintf(stderr, "got ack (%d) %s\n", ack, sha1_to_hex(result_sha1)); if (ack == ACK) return 0; multi_ack = 1; continue; } flushes--; } /* it is no error to fetch into a completely empty repo */ return count ? retval : 0; }
void send_commands() { kvstore_cmd_t cmd; kvstore_ack_t ack; char buf[100]; const char *delims = " "; char * parsed; int len; /* FIXME for now. Improve this by using a more * appropriate parser */ char *op, *kv_key, *kv_val; //int ret; memset(&cmd, 0, sizeof(kvstore_cmd_t)); memset(&ack, 0, sizeof(kvstore_ack_t)); do { memset(buf, 0, sizeof(buf)); printf("\n(kv) "); fflush(stdout); fgets(buf, sizeof(buf), stdin); parsed = strdup(buf); str_trim(&parsed); len = strlen(parsed); if (len == 0) { continue; } op = strtok(parsed, delims); // get the op kvstore_type_t kv_type = get_type(op); if (kv_type == KVSTORE_NONE) { printf("ERROR: Invalid Operation"); continue; } switch (kv_type) { case KVSTORE_EXIT: return; default: break; } // get the key and message kv_key = strtok(NULL, delims); if (kv_key == NULL) { printf("ERROR: Invalid Operation"); continue; } // if we're just using get if (kv_type == KVSTORE_GET) { kv_val = ""; } else { kv_val = strtok(NULL, "\0"); } // set the code and message then encrypt memset(&cmd, 0, sizeof(cmd)); cmd.type = kv_type; strncpy((char *)&cmd.payload.key, kv_key, KVSTORE_KEY_LEN); strncpy((char *)&cmd.payload.val, kv_val, KVSTORE_VAL_LEN); cmd.payload.key[strlen(kv_key)] = '\0'; // copy the IV memcpy(cmd.iv, iv, KVSTORE_AESIV_LEN); aes_setkey_enc(&aes, enckey, KVSTORE_AESKEY_BITS); aes_crypt_cbc(&aes, AES_ENCRYPT, sizeof(cmd.payload), iv, (const unsigned char *)&cmd.payload, (unsigned char *)&cmd.payload); if (send_data(&pfd, &cmd, sizeof(cmd))) { goto exit; } if (kv_type == KVSTORE_SET) { // just get the acknowledgement // TODO check content if (get_ack(&pfd, &ack)) { goto exit; } printf("OK"); } else if (kv_type == KVSTORE_GET) { // get the data if(get_resp(&pfd, &cmd)) { goto exit; } aes_setkey_dec(&aes, enckey, KVSTORE_AESKEY_BITS); // now decrypt aes_crypt_cbc(&aes, AES_DECRYPT, sizeof(cmd.payload), cmd.iv, (const unsigned char *)&cmd.payload, (unsigned char *)&cmd.payload); printf("%s", cmd.payload.val); } // printf("op: %s, title: %s, data: %s\n", op, kv_key, kv_msg); } while(1); exit: printf("error\n"); }