/* *************************************************** * Function: send_syn_ack * *************************************************** * Passive node calls this to send SYN_ACK and wait for * the final ACK packet. It tries a total of 6 times before * giving up. */ static bool send_syn_ack(mysocket_t sd, context_t *ctx, struct tcphdr* syn_packet) { struct tcphdr* ack_packet = (struct tcphdr *)calloc(1,(TH_MAX_OFFSET*sizeof(uint32_t))+STCP_MSS); unsigned int event; bool success = false; int num_tries = 1; struct timeval tstart; gettimeofday(&tstart, NULL); /*Start the timer */ network_send(sd, syn_packet, (TH_MIN_OFFSET*sizeof(uint32_t))); while((num_tries < MAX_RT_TRIES) && !success){ event = wait_for_event(sd, NETWORK_DATA, ctx, tstart); if (event & NETWORK_DATA) { network_recv(sd, ack_packet); our_dprintf("Passive (ACK waiting): Ack: %d, Seq:%d, Next Seq:%d, Last Ack Sent: %d\n", ack_packet->th_ack, ack_packet->th_seq, ctx->nxt_seq_num, ctx->last_ack_sent); success = ((ack_packet->th_flags == TH_ACK) && (ack_packet->th_ack == ctx->nxt_seq_num)); } else if (event==TIMEOUT){ our_dprintf("Passive Final INIT ACK not Received TIMEOUT!\n"); num_tries+=1; gettimeofday(&tstart, NULL); our_dprintf("PASSIVE - SEND SYN_ACK Packet with seq: %d and ack: %d \n", syn_packet->th_seq, syn_packet->th_ack); network_send(sd, syn_packet, (TH_MIN_OFFSET*sizeof(uint32_t))); } } if (success){ our_dprintf("PASSIVE - RCVD Last Ack Packet has seq: %d and ack: %d \n", ack_packet->th_seq, ack_packet->th_ack); ctx->recv_win = MIN(syn_packet->th_win, CWIN); } free(ack_packet); return success; }
/* *************************************************** * Function: passive_init * *************************************************** * Passive node waits for a SYN packet to arrive, it then * sends an SYN_ACK using another helper function (below) */ static bool passive_init(mysocket_t sd, context_t *ctx) { ctx->connection_state = CSTATE_LISTEN; struct tcphdr* syn_packet = (struct tcphdr *)calloc(1, (TH_MAX_OFFSET*sizeof(uint32_t))+STCP_MSS); /* Listen for a connection request */ while (true){ stcp_wait_for_event(sd, NETWORK_DATA, NULL); network_recv(sd, syn_packet); if (syn_packet->th_flags == TH_SYN){ break; } } our_dprintf("PASSIVE - RCVD SYN with seq: %d\n", syn_packet->th_seq); /* Prepare SYN_ACK*/ syn_packet->th_ack = syn_packet->th_seq + 1; syn_packet->th_seq = ctx->initial_sequence_num; syn_packet->th_off = TH_MIN_OFFSET; syn_packet->th_flags = TH_SYN | TH_ACK; syn_packet->th_win = RWIN; /*Update connection state variables */ ctx->last_ack_sent = syn_packet->th_ack; ctx->nxt_seq_num = ctx->initial_sequence_num + 1; ctx->connection_state = CSTATE_SYN_RCVD; ctx->seq_base = ctx->nxt_seq_num; our_dprintf("PASSIVE - SEND SYN_ACK Packet with seq: %d and ack: %d \n", syn_packet->th_seq, syn_packet->th_ack); bool success = send_syn_ack(sd, ctx, syn_packet); free(syn_packet); return success; }
static ssize_t read_all(void *dst, size_t len, int fd) { uintptr_t ptr = (uintptr_t) dst; while (len) { ssize_t ret = network_recv(fd, (void *) ptr, len, 0); if (ret < 0) return ret; ptr += ret; len -= ret; } return (ssize_t)(ptr - (uintptr_t) dst); }
static ssize_t network_read_line(struct iio_context_pdata *pdata, int desc, char *dst, size_t len) { size_t i; #ifdef __linux__ ssize_t ret; ret = network_recv(desc, dst, len, MSG_PEEK); if (ret < 0) return ret; /* Lookup for the trailing \n */ for (i = 0; i < (size_t) ret && dst[i] != '\n'; i++); /* No \n found? Just garbage data */ if (i == (size_t) ret) return -EIO; /* Advance the read offset to the byte following the \n */ return network_recv(desc, dst, i + 1, MSG_TRUNC); #else bool found = false; for (i = 0; i < len - 1; i++) { ssize_t ret = network_read_data(pdata, desc, dst + i, 1); if (ret < 0) return ret; if (dst[i] != '\n') found = true; else if (found) break; } dst[i] = '\0'; return (ssize_t) i; #endif }
gpointer network_reciever(gpointer data) { char *buffer; unsigned int level; sys_queue = g_async_queue_new(); msg_queue = g_async_queue_new(); pthread_detach(pthread_self()); while (1) { if (network_recv(&level, (void **)buffer, security->session) < 1) break; if (level == PACKET_SYS) g_async_queue_push(sys_queue, buffer); else if (level == PACKET_MSG) g_async_queue_push(msg_queue, buffer); else printf("Cannot specify target for packet(not sys and msg).\n"); } }
void NetworkWorker::run() { while (true) { { Glib::Threads::Mutex::Lock lock(m_mutex); if (m_network.disconnected) break; network_set_fds(&m_network); m_network.tv.tv_sec = 1; m_network.tv.tv_usec = 0; } network_select(&m_network); { Glib::Threads::Mutex::Lock lock(m_mutex); network_recv(&m_network); network_send(&m_network); m_stop = m_network.disconnected; if (m_network.has_data_in) { std::string data(m_network.buf_in); m_network.buf_in[0] = 0; m_network.has_data_in = FALSE; int pos; while ((pos = data.find("\r\n")) != std::string::npos) { m_in_data.push(data.substr(0, pos)); data = data.substr(pos + 2); } strcpy(m_network.buf_in, data.c_str()); strcat(m_network.buf_in, "\0"); if (strlen(m_network.buf_in) > 0) m_network.has_data_in = TRUE; } } { Glib::Threads::Mutex::Lock lock(m_mutex); m_dispatcher.emit(); } } }
/* *************************************************** * Function: sendrcv_syn * *************************************************** * Helper function for active-side network initiation. * It sends the SYN packet and waits for the right SYN_ACK */ static bool sendrcv_syn(mysocket_t sd, context_t *ctx, struct tcphdr* in_packet) { /* Set SYN Headers */ struct tcphdr* out_packet = (struct tcphdr *)calloc(1,(TH_MIN_OFFSET*sizeof(uint32_t))); out_packet->th_ack = 0; out_packet->th_seq = ctx->initial_sequence_num; out_packet->th_flags = TH_SYN; out_packet->th_off = TH_MIN_OFFSET; out_packet->th_win = RWIN; ctx->nxt_seq_num = ctx->initial_sequence_num + 1; /* SYN Packet = 1 byte */ our_dprintf("Active Sending SYN. Seq:%d\n", out_packet->th_seq); unsigned int event; bool success = false; int num_tries = 1; struct timeval tstart; gettimeofday(&tstart,NULL); /*start the timer */ network_send(sd, out_packet, (TH_MIN_OFFSET*sizeof(uint32_t))); /* Try sending the SYN a total of 6 times before giving up */ while ((num_tries < MAX_RT_TRIES) && !success){ event = wait_for_event(sd, NETWORK_DATA, ctx, tstart); if (event & NETWORK_DATA) { network_recv(sd, in_packet); /* Check to see if we got the right SYN_ACK */ success = ((in_packet->th_flags & (TH_SYN | TH_ACK)) && (in_packet->th_ack == ctx->nxt_seq_num)); } else if (event==TIMEOUT){ our_dprintf("Active - SYN TIMEOUT!, no SYN_ACK!\n"); gettimeofday(&tstart,NULL); num_tries+=1; our_dprintf("Active Resending SYN. Seq:%d\n", out_packet->th_seq); network_send(sd, out_packet, (TH_MIN_OFFSET*sizeof(uint32_t))); } } free(out_packet); return success; }
/* *************************************************** * Function: handle_network_data * *************************************************** * A packet has arrived. If its an ACK packet, call a helper * function that deals with acks. If the packet has data or it's * a FIN packet, then add the packet to the receiver buffer only * if it fits in the receiving window. If it doesn't fit, * drop the packet. If it fits, send an acknowledgement. */ static void handle_network_data(mysocket_t sd, context_t *ctx) { char *pkt = (char *)calloc(1, (TH_MAX_OFFSET*sizeof(uint32_t)) + STCP_MSS); size_t total_length = network_recv(sd, pkt); struct tcphdr* hdr = (struct tcphdr *)pkt; ctx->recv_win = MIN(hdr->th_win, CWIN); if (hdr->th_flags & TH_ACK) { handle_ack(hdr, sd, ctx); } size_t data_length = total_length - TCP_DATA_START(hdr); if (data_length>0 || (hdr->th_flags & TH_FIN)) { our_dprintf("Received %d bytes of data with seq: %d, last ack sent: %d\n", data_length, hdr->th_seq, ctx->last_ack_sent); /* Does the packet fit in the receiving window?*/ if ((hdr->th_seq + data_length)<=(ctx->last_ack_sent + RWIN)) { add_to_recv_buffer(ctx, pkt, total_length); if (hdr->th_seq == ctx->last_ack_sent){ /* The packet arrived in order. We can remove all in-order * packets from the receive buffer now */ our_dprintf("Packet In Order. Handling buffer\n"); handle_recv_buffer(sd, ctx); } else { if (hdr->th_seq > ctx->last_ack_sent) { our_dprintf("This packet is out of order. Adding to recv buffer\n"); } } send_ack(sd, ctx); } else { our_dprintf("Packet outside receiver buffer. Dropping!!!\n"); } } free(pkt); }
/** * Thread processing network events (coming from other nodes). * * This routine may set the network status to down as a side-effect * of calling network_recv(), and sets said status to up when the * network comes back. * * \param[in] dummy Unused * * \return NULL */ static void net_events_routine(void *dummy) { int dest_mbox; ExamsgMID mid; size_t size; char *msg; int s; exalog_as(EXAMSG_CMSGD_ID); exalog_trace("network events routine started"); while (!quit) { int status = network_status(); bool retry; if (status == -ENETDOWN) { network_waitup(); network_set_status(0); } do { s = network_recv(net_mh, &mid, &msg, &size, &dest_mbox); retry = (s < 0 && network_manageable(s) && s != -ENETDOWN); if (retry) os_sleep(1); } while (retry); /* Succeeded, the network status is ok */ if (s > 0 && status != 0) network_set_status(0); if (s == 0 || s == -ENETDOWN) continue; EXA_ASSERT(s > 0); /* Ping from another node for keepalive */ if (((ExamsgAny *)msg)->type == EXAMSG_PING) { EXA_ASSERT(dest_mbox == EXAMSG_CMSGD_ID); exalog_trace("received an EXAMSG_PING from %u:%s", mid.netid.node, mid.host); continue; } exalog_trace("delivering %" PRIzu " bytes to %d", size, dest_mbox); s = examsgMboxSend(&mid, examsgOwner(net_mh), dest_mbox, msg, size); switch (s) { case -ENXIO: /* The mailbox does not exist (yet). This is not an error: csupd may * not be started yet and we receive an examsg for it. * XXX Doesn't sound too good to me, and we should at least check that * the destination is indeed csupd */ break; case -ENOSPC: mailbox_full(dest_mbox, &mid, (Examsg *)msg); break; default: EXA_ASSERT_VERBOSE(s == size + sizeof(mid), "Error %d delivering message to %d", s, dest_mbox); break; } } }
static void client_console(int sock) { char client_buf[BABBLE_BUFFER_SIZE]; char *server_buf; char *user_buf =NULL; size_t user_buf_size=0; int cid = -1; int answer_expected = 0; while(getline(&user_buf, &user_buf_size, stdin) != -1){ /* truncate input if need be */ strncpy(client_buf, user_buf, BABBLE_BUFFER_SIZE); str_clean(client_buf); /* check command on client side */ cid = str_to_command(client_buf, &answer_expected); if(cid == -1){ continue; } if (network_send(sock, strlen(client_buf)+1,(void*) client_buf) != strlen(client_buf)+1){ perror("ERROR writing to socket"); break; } if(cid == TIMELINE){ /* specific protocol for timeline request */ int *t_length, i; if(network_recv(sock, (void**) &t_length) != sizeof(int)){ perror("ERROR in timeline protocol"); break; } printf("Timeline of size: %d\n", *t_length); /* recv only the last BABBLE_TIMELINE_MAX */ int to_recv= (*t_length < BABBLE_TIMELINE_MAX)? *t_length : BABBLE_TIMELINE_MAX; free(t_length); for(i=0; i< to_recv; i++){ if(network_recv(sock, (void**) &server_buf) < 0){ perror("ERROR reading from socket"); break; } printf("%s", server_buf); free(server_buf); } if(i != to_recv){ break; } } else{ if(answer_expected){ if(network_recv(sock, (void**) &server_buf) < 0){ perror("ERROR reading from socket"); break; } printf("%s", server_buf); free(server_buf); } } } printf("### Client exiting \n"); }
static ssize_t network_read_data(struct iio_context_pdata *pdata, int desc, char *dst, size_t len) { return network_recv(desc, dst, len, 0); }