コード例 #1
0
ファイル: output_udp.c プロジェクト: crazyleen/mjpeg-streamer
static int output_sendto (int sock, const void *frame, int frame_size,
		struct sockaddr_in *addr)
{
	struct frame_info {
		int8_t 	mask[2];	// 'FM' const
		int32_t	len;	//
		int8_t	data[UDPDATA_MAX_SIZE];
	}__attribute__((__packed__));

	struct frame_info fm;
	fm.mask[0] = 'F';
	fm.mask[1] = 'M';
	fm.len = 0;

	unsigned char *p = NULL;
    p = (unsigned char *)frame;
    while(frame_size > 0) {
		static int cnt = 0;
    	if(frame_size < UDPDATA_MAX_SIZE)
    		fm.len = frame_size;
    	else
    		fm.len = UDPDATA_MAX_SIZE;

    	memcpy(fm.data, p, fm.len);
    	int i;
    	for(i = 0; i < 5; i++){
    		sendto(sock, &fm, sizeof(fm), 0, (struct sockaddr*)addr, sizeof(struct sockaddr_in));

    		char answer[128];
    		int len;
    		int ret;
    		fd_set input;
    		struct timeval timeout;
    		FD_ZERO(&input);
    		FD_SET(sock, &input);

    		timeout.tv_sec = 0;
    		timeout.tv_usec = 5000;
    		ret = select(sock + 1, &input, NULL, NULL, &timeout);
    		if (ret < 0) {
    			perror("select");
    			break;
    		} else if (ret == 0) {
				if(cnt == 0)
					printf("ERROR: no recv\n");
    			printf("%d\r", cnt++);
				fflush(stdout);
    		} else {
    			if (FD_ISSET(sock, &input)) {
					cnt = 0;
    	    		len = recvfrom(sock, answer, sizeof(answer), 0, NULL, 0);
    	    		if(len > 0)
    	    			if(strncmp(answer, "OK", 2) == 0)
    	    				break;
    			}
    		}

    	}
    	frame_size-=fm.len;
    	p += fm.len;
    }
    p = NULL;

    return 0;
}
コード例 #2
0
ファイル: client.c プロジェクト: tseeley/serval-dna
int getReplyPackets(int method,int peer,int batchP,
		    struct response_set *responses,
		    unsigned char *transaction_id,int timeout)
{
  /* set timeout alarm */
  
  /* get packets until timeout, or until we get a packet from the specified peer
     if method==REQ_SERIAL.  If REQ_SERIAL we also reject packets from other 
     senders as they must be spoofs.
  */
  struct timeval t;
  int timeout_secs;
  int timeout_usecs;
  int to=timeout;

  if (debug>1) printf("getReplyPackets(policy=%d)\n",method);

  /* Work out when the timeout will expire */
  gettimeofday(&t,NULL); 
  timeout_secs=t.tv_sec; timeout_usecs=t.tv_usec;
  if (to>1000) { timeout_secs+=(to/1000); to=to%1000; }
  timeout_usecs+=to*1000; if (timeout_usecs>1000000) { timeout_secs++; timeout_usecs-=1000000; }
  
  while(1) {
    unsigned char buffer[16384];
    socklen_t recvaddrlen=sizeof(recvaddr);
    struct pollfd fds;
    client_port=((struct sockaddr_in*)&recvaddr)->sin_port;
    bzero((void *)&recvaddr,sizeof(recvaddr));
    fds.fd=sock; fds.events=POLLIN;
    while (poll(&fds,1,10 /* wait for 10ms at a time */)<1)
      {
	gettimeofday(&t,NULL);
	if (t.tv_sec>timeout_secs) return 1;
	if (t.tv_sec==timeout_secs&&t.tv_usec>=timeout_usecs) return 1;
      }
    client_port=((struct sockaddr_in*)&recvaddr)->sin_port;
    int len=recvfrom(sock,buffer,sizeof(buffer),0,&recvaddr,&recvaddrlen);
    client_addr=((struct sockaddr_in*)&recvaddr)->sin_addr;
    if (debug) fprintf(stderr,"Received reply from %s (len=%d).\n",inet_ntoa(client_addr),len);
    if (debug>1) dump("recvaddr",(unsigned char *)&recvaddr,recvaddrlen);
    if (debug>2) dump("packet",(unsigned char *)buffer,len);
    if (dropPacketP(len)) {
      if (debug) fprintf(stderr,"Simulation mode: Dropped packet due to simulated link parameters.\n");
      continue;
    }
    if (!packetOk(buffer,len,transaction_id)) {
      /* Packet passes tests - extract responses and append them to the end of the response list */
      if (extractResponses(client_addr,buffer,len,responses)) 
	return setReason("Problem extracting response fields from reply packets");
      if (method==REQ_SERIAL||method==REQ_FIRSTREPLY) {
	if (!batchP) return 0;
	/* In batch mode we need ACTION_DONE to mark end of transmission. 
	   While it gets sent last, out-of-order delivery means we can't rely on
	   such a nice arrangement. */
	{
	  /* XXX inefficient for long lists.
	     XXX can be made better by working backwards from end using double-linked list and 
	     remembering the previous length of the list */
	  struct response *r=responses->responses;
	  while(r)
	    {
	      if (r->code==ACTION_DONE) return 0;
	      r=r->next;
	    }
	}
      }
      else {
	if (debug>1) printf("Waiting for more packets, since called with policy %d\n",method);
      }
    } else {
      if (debug) setReason("Ignoring invalid packet");
    }      
  }
}
コード例 #3
0
ファイル: rtpproto.c プロジェクト: BlackMael/DirectEncode
static int rtp_read(URLContext *h, uint8_t *buf, int size)
{
    RTPContext *s = h->priv_data;
    struct sockaddr_in from;
    socklen_t from_len;
    int len, fd_max, n;
    fd_set rfds;
#if 0
    for(;;) {
        from_len = sizeof(from);
        len = recvfrom (s->rtp_fd, buf, size, 0,
                        (struct sockaddr *)&from, &from_len);
        if (len < 0) {
            if (ff_neterrno() == FF_NETERROR(EAGAIN) ||
                ff_neterrno() == FF_NETERROR(EINTR))
                continue;
            return AVERROR(EIO);
        }
        break;
    }
#else
    for(;;) {
        /* build fdset to listen to RTP and RTCP packets */
        FD_ZERO(&rfds);
        fd_max = s->rtp_fd;
        FD_SET(s->rtp_fd, &rfds);
        if (s->rtcp_fd > fd_max)
            fd_max = s->rtcp_fd;
        FD_SET(s->rtcp_fd, &rfds);
        n = select(fd_max + 1, &rfds, NULL, NULL, NULL);
        if (n > 0) {
            /* first try RTCP */
            if (FD_ISSET(s->rtcp_fd, &rfds)) {
                from_len = sizeof(from);
                len = recvfrom (s->rtcp_fd, buf, size, 0,
                                (struct sockaddr *)&from, &from_len);
                if (len < 0) {
                    if (ff_neterrno() == FF_NETERROR(EAGAIN) ||
                        ff_neterrno() == FF_NETERROR(EINTR))
                        continue;
                    return AVERROR(EIO);
                }
                break;
            }
            /* then RTP */
            if (FD_ISSET(s->rtp_fd, &rfds)) {
                from_len = sizeof(from);
                len = recvfrom (s->rtp_fd, buf, size, 0,
                                (struct sockaddr *)&from, &from_len);
                if (len < 0) {
                    if (ff_neterrno() == FF_NETERROR(EAGAIN) ||
                        ff_neterrno() == FF_NETERROR(EINTR))
                        continue;
                    return AVERROR(EIO);
                }
                break;
            }
        }
    }
#endif
    return len;
}
コード例 #4
0
ファイル: dtls_echo.c プロジェクト: a34729t/exp
void dtls_server (int port)
{
    int listen_sd;
    int sock, ret;
    struct sockaddr_in sa_serv;
    char buffer[MAX_MESSAGE_SIZE];
    int mtu = 1400;
    unsigned char sequence[8];
    gnutls_datum_t cookie_key; // Should this be regenerated for each incoming conn?
    
    // Certs
    char *cafile = "./certs/cert.pem";
    char *crlfile = "./certs/crl.pem";
    char *certfile = "./certs/cert.pem";
    char *keyfile = "./certs/key.pem";
    
    // Configure credentials and session
    gnutls_certificate_allocate_credentials (&x509_cred);
    gnutls_certificate_set_x509_trust_file (x509_cred, cafile, GNUTLS_X509_FMT_PEM);
    gnutls_certificate_set_x509_crl_file (x509_cred, crlfile, GNUTLS_X509_FMT_PEM);
    ret = gnutls_certificate_set_x509_key_file (x509_cred, certfile, keyfile,
                                          GNUTLS_X509_FMT_PEM);
    if (ret < 0) Die("No keys or certs were found");
    
    // Set some crypto params and other stuff
    generate_dh_params (); // Diffie-Hellman
    gnutls_priority_init (&priority_cache,
            "PERFORMANCE:-VERS-TLS-ALL:+VERS-DTLS1.0:%SERVER_PRECEDENCE", 
            NULL);
    gnutls_key_generate (&cookie_key, GNUTLS_COOKIE_KEY_SIZE);
    
    /* Socket operations
     */
    listen_sd = socket (AF_INET, SOCK_DGRAM, 0);

    memset (&sa_serv, '\0', sizeof (sa_serv));
    sa_serv.sin_family = AF_INET;
    sa_serv.sin_addr.s_addr = INADDR_ANY;
    sa_serv.sin_port = htons (port);

/* DTLS requires the IP don't fragment (DF) bit to be set */
#if defined(IP_DONTFRAG)
      int optval = 1;
      setsockopt (listen_sd, IPPROTO_IP, IP_DONTFRAG,
                  (const void *) &optval, sizeof (optval));
#elif defined(IP_MTU_DISCOVER)
      int optval = IP_PMTUDISC_DO;
      setsockopt(listen_sd, IPPROTO_IP, IP_MTU_DISCOVER, 
                 (const void*) &optval, sizeof (optval));
#endif

    bind (listen_sd, (struct sockaddr *) &sa_serv, sizeof (sa_serv));

    printf ("UDP server ready. Listening to port '%d'.\n\n", port);
    
    for (;;)
    {
        printf ("Waiting for connection...\n");

        sock = wait_for_connection (listen_sd);
        if (sock < 0) continue;

        // Someone is accepting a connection, get data structures ready
        priv_data_st priv;
        gnutls_dtls_prestate_st prestate;
        gnutls_session_t session;
        struct sockaddr_in cli_addr;
        socklen_t cli_addr_size;

        cli_addr_size = sizeof (cli_addr);
        ret = recvfrom (sock, buffer, sizeof (buffer), MSG_PEEK,
                        (struct sockaddr *) &cli_addr, &cli_addr_size);
        if (ret > 0)
        {
            memset (&prestate, 0, sizeof (prestate));
            ret = gnutls_dtls_cookie_verify (&cookie_key, &cli_addr,
                                             sizeof (cli_addr), buffer, ret,
                                             &prestate);
            if (ret < 0) /* cookie not valid */
            {
                priv_data_st s;

                memset (&s, 0, sizeof (s));
                s.fd = sock;
                s.cli_addr = (void *) &cli_addr;
                s.cli_addr_size = sizeof (cli_addr);

                printf ("Sending hello verify request to %s\n",
                        human_addr ((struct sockaddr *) &cli_addr,
                                    sizeof (cli_addr), buffer,
                                    sizeof (buffer)));

                gnutls_dtls_cookie_send (&cookie_key, &cli_addr,
                                         sizeof (cli_addr), &prestate,
                                         (gnutls_transport_ptr_t) & s,
                                         push_func);

                /* discard peeked data */
                recvfrom (sock, buffer, sizeof (buffer), 0,
                          (struct sockaddr *) &cli_addr, &cli_addr_size);
                usleep (100);
                continue;
              }
            printf ("Accepted connection from %s\n",
                    human_addr ((struct sockaddr *)
                                &cli_addr, sizeof (cli_addr), buffer,
                                sizeof (buffer)));
          }
        else
          continue;

        session = initialize_tls_session ();
        gnutls_dtls_prestate_set (session, &prestate);
        gnutls_dtls_set_mtu (session, mtu);

        priv.session = session;
        priv.fd = sock;
        priv.cli_addr = (struct sockaddr *) &cli_addr;
        priv.cli_addr_size = sizeof (cli_addr);

        gnutls_transport_set_ptr (session, &priv);
        gnutls_transport_set_push_function (session, push_func);
        gnutls_transport_set_pull_function (session, pull_func);
        gnutls_transport_set_pull_timeout_function (session, pull_timeout_func);

        do
          {
            ret = gnutls_handshake (session);
          }
        while (ret < 0 && gnutls_error_is_fatal (ret) == 0);

        if (ret < 0)
          {
            fprintf (stderr, "Error in handshake(): %s\n",
                     gnutls_strerror (ret));
            gnutls_deinit (session);
            continue;
          }

        printf ("- Handshake was completed\n");

        for (;;)
          {
            do
              {
                ret = gnutls_record_recv_seq (session, buffer, MAX_MESSAGE_SIZE,
                                              sequence);
              }
            while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);

            if (ret < 0)
              {
                fprintf (stderr, "Error in recv(): %s\n",
                         gnutls_strerror (ret));
                break;
              }
            if (ret == 0)
              {
                printf ("EOF\n\n");
                break;
              }
            buffer[ret] = 0;
            printf ("received[%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x]: %s\n",
                    sequence[0], sequence[1], sequence[2], sequence[3],
                    sequence[4], sequence[5], sequence[6], sequence[7], buffer);

            /* reply back */
            ret = gnutls_record_send (session, buffer, ret);
            if (ret < 0)
              {
                fprintf (stderr, "Error in send(): %s\n",
                         gnutls_strerror (ret));
                break;
              }
          }

        gnutls_bye (session, GNUTLS_SHUT_WR);
        gnutls_deinit (session);

    }
    close (listen_sd);

    gnutls_certificate_free_credentials (x509_cred);
    gnutls_priority_deinit (priority_cache);

    gnutls_global_deinit ();
}
コード例 #5
0
ファイル: secure.c プロジェクト: Ar0xA/ossec-hids
/** void HandleSecure() v0.3
 * Handle the secure connections
 */
void HandleSecure()
{
    int agentid;

    char buffer[OS_MAXSTR +1];
    char cleartext_msg[OS_MAXSTR +1];
    char srcip[IPSIZE +1];
    char *tmp_msg;
    char srcmsg[OS_FLSIZE +1];


    int recv_b;

    struct sockaddr_in peer_info;
    socklen_t peer_size;


    /* Send msg init */
    send_msg_init();


    /* Initializing key mutex. */
    keyupdate_init();


    /* Initializing manager */
    manager_init(0);


    /* Creating Ar forwarder thread */
    if(CreateThread(AR_Forward, (void *)NULL) != 0)
    {
        ErrorExit(THREAD_ERROR, ARGV0);
    }

    /* Creating wait_for_msgs thread */
    if(CreateThread(wait_for_msgs, (void *)NULL) != 0)
    {
        ErrorExit(THREAD_ERROR, ARGV0);
    }


    /* Connecting to the message queue
     * Exit if it fails.
     */
    if((logr.m_queue = StartMQ(DEFAULTQUEUE,WRITE)) < 0)
    {
        ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQUEUE);
    }


    verbose(AG_AX_AGENTS, ARGV0, MAX_AGENTS);


    /* Reading authentication keys */
    verbose(ENC_READ, ARGV0);

    OS_ReadKeys(&keys);

    debug1("%s: DEBUG: OS_StartCounter.", ARGV0);
    OS_StartCounter(&keys);
    debug1("%s: DEBUG: OS_StartCounter completed.", ARGV0);


    /* setting up peer size */
    peer_size = sizeof(peer_info);
    logr.peer_size = sizeof(peer_info);


    /* Initializing some variables */
    memset(buffer, '\0', OS_MAXSTR +1);
    memset(cleartext_msg, '\0', OS_MAXSTR +1);
    memset(srcmsg, '\0', OS_FLSIZE +1);
    tmp_msg = NULL;



    /* loop in here */
    while(1)
    {
        /* Receiving message  */
        recv_b = recvfrom(logr.sock, buffer, OS_MAXSTR, 0,
                (struct sockaddr *)&peer_info, &peer_size);


        /* Nothing received */
        if(recv_b <= 0)
        {
            continue;
        }


        /* Setting the source ip */
        strncpy(srcip, inet_ntoa(peer_info.sin_addr), IPSIZE);
        srcip[IPSIZE] = '\0';



        /* Getting a valid agentid */
        if(buffer[0] == '!')
        {
            tmp_msg = buffer;
            tmp_msg++;


            /* We need to make sure that we have a valid id
             * and that we reduce the recv buffer size.
             */
            while(isdigit((int)*tmp_msg))
            {
                tmp_msg++;
                recv_b--;
            }

            if(*tmp_msg != '!')
            {
                merror(ENCFORMAT_ERROR, __local_name, srcip);
                continue;
            }

            *tmp_msg = '\0';
            tmp_msg++;
            recv_b-=2;

            agentid = OS_IsAllowedDynamicID(&keys, buffer +1, srcip);
            if(agentid == -1)
            {
                if(check_keyupdate())
                {
                    agentid = OS_IsAllowedDynamicID(&keys, buffer +1, srcip);
                    if(agentid == -1)
                    {
                        merror(ENC_IP_ERROR, ARGV0, srcip);
                        continue;
                    }
                }
                else
                {
                    merror(ENC_IP_ERROR, ARGV0, srcip);
                    continue;
                }
            }
        }
        else
        {
            agentid = OS_IsAllowedIP(&keys, srcip);
            if(agentid < 0)
            {
                if(check_keyupdate())
                {
                    agentid = OS_IsAllowedIP(&keys, srcip);
                    if(agentid == -1)
                    {
                        merror(DENYIP_WARN,ARGV0,srcip);
                        continue;
                    }
                }
                else
                {
                    merror(DENYIP_WARN,ARGV0,srcip);
                    continue;
                }
            }
            tmp_msg = buffer;
        }


        /* Decrypting the message */
        tmp_msg = ReadSecMSG(&keys, tmp_msg, cleartext_msg,
                             agentid, recv_b -1);
        if(tmp_msg == NULL)
        {
            /* If duplicated, a warning was already generated */
            continue;
        }


        /* Check if it is a control message */
        if(IsValidHeader(tmp_msg))
        {
            /* We need to save the peerinfo if it is a control msg */
            memcpy(&keys.keyentries[agentid]->peer_info, &peer_info, peer_size);
            keys.keyentries[agentid]->rcvd = time(0);

            save_controlmsg(agentid, tmp_msg);

            continue;
        }


        /* Generating srcmsg */
        snprintf(srcmsg, OS_FLSIZE,"(%s) %s",keys.keyentries[agentid]->name,
                                             keys.keyentries[agentid]->ip->ip);


        /* If we can't send the message, try to connect to the
         * socket again. If it not exit.
         */
        if(SendMSG(logr.m_queue, tmp_msg, srcmsg,
                   SECURE_MQ) < 0)
        {
            merror(QUEUE_ERROR, ARGV0, DEFAULTQUEUE, strerror(errno));

            if((logr.m_queue = StartMQ(DEFAULTQUEUE, WRITE)) < 0)
            {
                ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQUEUE);
            }
        }
    }
}
コード例 #6
0
static int rtp_read(URLContext *h, uint8_t *buf, int size)
{
	RTPContext *s = h->priv_data;
	struct sockaddr_storage from;
	socklen_t from_len;
	int len, n;
	struct pollfd p[2] = {{s->rtp_fd, POLLIN, 0}, {s->rtcp_fd, POLLIN, 0}};

#if 0
	for(;;)
	{
		from_len = sizeof(from);
		len = recvfrom (s->rtp_fd, buf, size, 0,
		(struct sockaddr *)&from, &from_len);
		if (len < 0)
		{
			if (ff_neterrno() == AVERROR(EAGAIN) ||
			ff_neterrno() == AVERROR(EINTR))
				continue;
			return AVERROR(EIO);
		}
		break;
	}
#else
	for(;;)
	{
		if (url_interrupt_cb())
			return AVERROR_EXIT;
		/* build fdset to listen to RTP and RTCP packets */
		n = poll(p, 2, 100);
		if (n > 0)
		{
			/* first try RTCP */
			if (p[1].revents & POLLIN)
			{
				from_len = sizeof(from);
				len = recvfrom (s->rtcp_fd, buf, size, 0,
				(struct sockaddr *)&from, &from_len);
				if (len < 0)
				{
					if (ff_neterrno() == AVERROR(EAGAIN) ||
					ff_neterrno() == AVERROR(EINTR))
						continue;
					return AVERROR(EIO);
				}
				break;
			}
			/* then RTP */
			if (p[0].revents & POLLIN)
			{
				from_len = sizeof(from);
				len = recvfrom (s->rtp_fd, buf, size, 0,
				(struct sockaddr *)&from, &from_len);
				if (len < 0)
				{
					if (ff_neterrno() == AVERROR(EAGAIN) ||
					ff_neterrno() == AVERROR(EINTR))
						continue;
					return AVERROR(EIO);
				}
				break;
			}
		}
		else if (n < 0)
		{
			if (ff_neterrno() == AVERROR(EINTR))
				continue;
			return AVERROR(EIO);
		}
	}
#endif
	return len;
}
コード例 #7
0
ファイル: rudp.c プロジェクト: AfifFaris/Reliable-UDP
/* Callback function executed when something is received on fd */
int receive_callback(int file, void *arg) {
  char buf[sizeof(struct rudp_packet)];
  struct sockaddr_in sender;
  size_t sender_length = sizeof(struct sockaddr_in);
  recvfrom(file, &buf, sizeof(struct rudp_packet), 0, (struct sockaddr *)&sender, &sender_length);

  struct rudp_packet *received_packet = malloc(sizeof(struct rudp_packet));
  if(received_packet == NULL) {
    fprintf(stderr, "receive_callback: Error allocating packet\n");
    return -1;
  }
  memcpy(received_packet, &buf, sizeof(struct rudp_packet));
  
  struct rudp_hdr rudpheader = received_packet->header;
  char type[5];
  short t = rudpheader.type;
  if(t == 1)
    strcpy(type, "DATA");
  else if(t == 2)
    strcpy(type, "ACK");
  else if(t == 4)
    strcpy(type, "SYN");
  else if(t==5)
    strcpy(type, "FIN");
  else
    strcpy(type, "BAD");

  printf("Received %s packet from %s:%d seq number=%u on socket=%d\n",type, 
       inet_ntoa(sender.sin_addr), ntohs(sender.sin_port),rudpheader.seqno,file);

  /* Locate the correct socket in the socket list */
  if(socket_list_head == NULL) {
    fprintf(stderr, "Error: attempt to receive on invalid socket. No sockets in the list\n");
    return -1;
  }
  else {
    /* We have sockets to check */
    struct rudp_socket_list *curr_socket = socket_list_head;
    while(curr_socket != NULL) {
      if((int)curr_socket->rsock == file) {
        break;
      }
      curr_socket = curr_socket->next;
    }
    if((int)curr_socket->rsock == file) {
      /* We found the correct socket, now see if a session already exists for this peer */
      if(curr_socket->sessions_list_head == NULL) {
        /* The list is empty, so we check if the sender has initiated the protocol properly (by sending a SYN) */
        if(rudpheader.type == RUDP_SYN) {
          /* SYN Received. Create a new session at the head of the list */
          u_int32_t seqno = rudpheader.seqno + 1;
          create_receiver_session(curr_socket, seqno, &sender);
          /* Respond with an ACK */
          struct rudp_packet *p = create_rudp_packet(RUDP_ACK, seqno, 0, NULL);
          send_packet(true, (rudp_socket_t)file, p, &sender);
          free(p);
        }
        else {
          /* No sessions exist and we got a non-SYN, so ignore it */
        }
      }
      else {
        /* Some sessions exist to be checked */
        bool_t session_found = false;
        struct session *curr_session = curr_socket->sessions_list_head;
        struct session *last_session;
        while(curr_session != NULL) {
          if(curr_session->next == NULL) {
            last_session = curr_session;
          }
          if(compare_sockaddr(&curr_session->address, &sender) == 1) {
            /* Found an existing session */
            session_found = true;
            break;
          }

          curr_session = curr_session->next;
        }
        if(session_found == false) {
          /* No session was found for this peer */
          if(rudpheader.type == RUDP_SYN) {
            /* SYN Received. Send an ACK and create a new session */
            u_int32_t seqno = rudpheader.seqno + 1;
            create_receiver_session(curr_socket, seqno, &sender);          
            struct rudp_packet *p = create_rudp_packet(RUDP_ACK, seqno, 0, NULL);
            send_packet(true, (rudp_socket_t)file, p, &sender);
            free(p);
          }
          else {
            /* Session does not exist and non-SYN received - ignore it */
          }
        }
        else {
          /* We found a matching session */ 
          if(rudpheader.type == RUDP_SYN) {
            if(curr_session->receiver == NULL || curr_session->receiver->status == OPENING) {
              /* Create a new receiver session and ACK the SYN*/
              struct receiver_session *new_receiver_session = malloc(sizeof(struct receiver_session));
              if(new_receiver_session == NULL) {
                fprintf(stderr, "receive_callback: Error allocating receiver session\n");
                return -1;
              }
              new_receiver_session->expected_seqno = rudpheader.seqno + 1;
              new_receiver_session->status = OPENING;
              new_receiver_session->session_finished = false;
              curr_session->receiver = new_receiver_session;

              u_int32_t seqno = curr_session->receiver->expected_seqno;
              struct rudp_packet *p = create_rudp_packet(RUDP_ACK, seqno, 0, NULL);
              send_packet(true, (rudp_socket_t)file, p, &sender);
              free(p);
            }
            else {
              /* Received a SYN when there is already an active receiver session, so we ignore it */
            }
          }
          if(rudpheader.type == RUDP_ACK) {
            u_int32_t ack_sqn = received_packet->header.seqno;
            if(curr_session->sender->status == SYN_SENT) {
              /* This an ACK for a SYN */
              u_int32_t syn_sqn = curr_session->sender->seqno;
              if( (ack_sqn - 1) == syn_sqn) {
                /* Delete the retransmission timeout */
                event_timeout_delete(timeout_callback, curr_session->sender->syn_timeout_arg);
                struct timeoutargs *t = (struct timeoutargs *)curr_session->sender->syn_timeout_arg;
                free(t->packet);
                free(t->recipient);
                free(t);
                curr_session->sender->status = OPEN;
                while(curr_session->sender->data_queue != NULL) {
                  /* Check if the window is already full */
                  if(curr_session->sender->sliding_window[RUDP_WINDOW-1] != NULL) {
                    break;
                  }
                  else {
                    int index;
                    int i;
                    /* Find the first unused window slot */
                    for(i = RUDP_WINDOW-1; i >= 0; i--) {
                      if(curr_session->sender->sliding_window[i] == NULL) {
                        index = i;
                      }
                    }
                    /* Send packet, add to window and remove from queue */
                    u_int32_t seqno = ++syn_sqn;
                    int len = curr_session->sender->data_queue->len;
                    char *payload = curr_session->sender->data_queue->item;
                    struct rudp_packet *datap = create_rudp_packet(RUDP_DATA, seqno, len, payload);
                    curr_session->sender->seqno += 1;
                    curr_session->sender->sliding_window[index] = datap;
                    curr_session->sender->retransmission_attempts[index] = 0;
                    struct data *temp = curr_session->sender->data_queue;
                    curr_session->sender->data_queue = curr_session->sender->data_queue->next;
                    free(temp->item);
                    free(temp);

                    send_packet(false, (rudp_socket_t)file, datap, &sender);
                  }
                }
              }
            }
            else if(curr_session->sender->status == OPEN) {
              /* This is an ACK for DATA */
              if(curr_session->sender->sliding_window[0] != NULL) {
                if(curr_session->sender->sliding_window[0]->header.seqno == (rudpheader.seqno-1)) {
                  /* Correct ACK received. Remove the first window item and shift the rest left */
                  event_timeout_delete(timeout_callback, curr_session->sender->data_timeout_arg[0]);
                  struct timeoutargs *args = (struct timeoutargs *)curr_session->sender->data_timeout_arg[0];
                  free(args->packet);
                  free(args->recipient);
                  free(args);
                  free(curr_session->sender->sliding_window[0]);

                  int i;
                  if(RUDP_WINDOW == 1) {
                    curr_session->sender->sliding_window[0] = NULL;
                    curr_session->sender->retransmission_attempts[0] = 0;
                    curr_session->sender->data_timeout_arg[0] = NULL;
                  }
                  else {
                    for(i = 0; i < RUDP_WINDOW - 1; i++) {
                      curr_session->sender->sliding_window[i] = curr_session->sender->sliding_window[i+1];
                      curr_session->sender->retransmission_attempts[i] = curr_session->sender->retransmission_attempts[i+1];
                      curr_session->sender->data_timeout_arg[i] = curr_session->sender->data_timeout_arg[i+1];

                      if(i == RUDP_WINDOW-2) {
                        curr_session->sender->sliding_window[i+1] = NULL;
                        curr_session->sender->retransmission_attempts[i+1] = 0;
                        curr_session->sender->data_timeout_arg[i+1] = NULL;
                      }
                    }
                  }

                  while(curr_session->sender->data_queue != NULL) {
                    if(curr_session->sender->sliding_window[RUDP_WINDOW-1] != NULL) {
                      break;
                    }
                    else {
                      int index;
                      int i;
                      /* Find the first unused window slot */
                      for(i = RUDP_WINDOW-1; i >= 0; i--) {
                        if(curr_session->sender->sliding_window[i] == NULL) {
                          index = i;
                        }
                      }                      
                      /* Send packet, add to window and remove from queue */
                      curr_session->sender->seqno = curr_session->sender->seqno + 1;                      
                      u_int32_t seqno = curr_session->sender->seqno;
                      int len = curr_session->sender->data_queue->len;
                      char *payload = curr_session->sender->data_queue->item;
                      struct rudp_packet *datap = create_rudp_packet(RUDP_DATA, seqno, len, payload);
                      curr_session->sender->sliding_window[index] = datap;
                      curr_session->sender->retransmission_attempts[index] = 0;
                      struct data *temp = curr_session->sender->data_queue;
                      curr_session->sender->data_queue = curr_session->sender->data_queue->next;
                      free(temp->item);
                      free(temp);
                      send_packet(false, (rudp_socket_t)file, datap, &sender);
                    }
                  }
                  if(curr_socket->close_requested) {
                    /* Can the socket be closed? */
                    struct session *head_sessions = curr_socket->sessions_list_head;
                    while(head_sessions != NULL) {
                      if(head_sessions->sender->session_finished == false) {
                        if(head_sessions->sender->data_queue == NULL &&  
                           head_sessions->sender->sliding_window[0] == NULL && 
                           head_sessions->sender->status == OPEN) {
                          head_sessions->sender->seqno += 1;                      
                          struct rudp_packet *p = create_rudp_packet(RUDP_FIN, head_sessions->sender->seqno, 0, NULL);
                          send_packet(false, (rudp_socket_t)file, p, &head_sessions->address);
                          free(p);
                          head_sessions->sender->status = FIN_SENT;
                        }
                      }
                      head_sessions = head_sessions->next;
                    }
                  }
                }
              }
            }
            else if(curr_session->sender->status == FIN_SENT) {
              /* Handle ACK for FIN */
              if( (curr_session->sender->seqno + 1) == received_packet->header.seqno) {
                event_timeout_delete(timeout_callback, curr_session->sender->fin_timeout_arg);
                struct timeoutargs *t = curr_session->sender->fin_timeout_arg;
                free(t->packet);
                free(t->recipient);
                free(t);
                curr_session->sender->session_finished = true;
                if(curr_socket->close_requested) {
                  /* See if we can close the socket */
                  struct session *head_sessions = curr_socket->sessions_list_head;
                  bool_t all_done = true;
                  while(head_sessions != NULL) {
                    if(head_sessions->sender->session_finished == false) {
                      all_done = false;
                    }
                    else if(head_sessions->receiver != NULL && head_sessions->receiver->session_finished == false) {
                      all_done = false;
                    }
                    else {
                      free(head_sessions->sender);
                      if(head_sessions->receiver) {
                        free(head_sessions->receiver);
                      }
                    }

                    struct session *temp = head_sessions;
                    head_sessions = head_sessions->next;
                    free(temp);
                  }
                  if(all_done) {
                    if(curr_socket->handler != NULL) {
                      curr_socket->handler((rudp_socket_t)file, RUDP_EVENT_CLOSED, &sender);
                      event_fd_delete(receive_callback, (rudp_socket_t)file);
                      close(file);
                      free(curr_socket);
                    }
                  }
                }
              }
              else {
                /* Received incorrect ACK for FIN - ignore it */
              }
            }
          }
          else if(rudpheader.type == RUDP_DATA) {
            /* Handle DATA packet. If the receiver is OPENING, it can transition to OPEN */
            if(curr_session->receiver->status == OPENING) {
              if(rudpheader.seqno == curr_session->receiver->expected_seqno) {
                curr_session->receiver->status = OPEN;
              }
            }

            if(rudpheader.seqno == curr_session->receiver->expected_seqno) {
              /* Sequence numbers match - ACK the data */
              u_int32_t seqno = rudpheader.seqno + 1;
              curr_session->receiver->expected_seqno = seqno;
              struct rudp_packet *p = create_rudp_packet(RUDP_ACK, seqno, 0, NULL);
  
              send_packet(true, (rudp_socket_t)file, p, &sender);
              free(p);
              
              /* Pass the data up to the application */
              if(curr_socket->recv_handler != NULL)
                curr_socket->recv_handler((rudp_socket_t)file, &sender, 
                              (void*)&received_packet->payload, received_packet->payload_length);
            }
            /* Handle the case where an ACK was lost */
            else if(SEQ_GEQ(rudpheader.seqno, (curr_session->receiver->expected_seqno - RUDP_WINDOW)) &&
                SEQ_LT(rudpheader.seqno, curr_session->receiver->expected_seqno)) {
              u_int32_t seqno = rudpheader.seqno + 1;
              struct rudp_packet *p = create_rudp_packet(RUDP_ACK, seqno, 0, NULL);
              send_packet(true, (rudp_socket_t)file, p, &sender);
              free(p);
            }
          }
          else if(rudpheader.type == RUDP_FIN) {
            if(curr_session->receiver->status == OPEN) {
              if(rudpheader.seqno == curr_session->receiver->expected_seqno) {
                /* If the FIN is correct, we can ACK it */
                u_int32_t seqno = curr_session->receiver->expected_seqno + 1;
                struct rudp_packet *p = create_rudp_packet(RUDP_ACK, seqno, 0, NULL);
                send_packet(true, (rudp_socket_t)file, p, &sender);
                free(p);
                curr_session->receiver->session_finished = true;

                if(curr_socket->close_requested) {
                  /* Can we close the socket now? */
                  struct session *head_sessions = curr_socket->sessions_list_head;
                  int all_done = true;
                  while(head_sessions != NULL) {
                    if(head_sessions->sender->session_finished == false) {
                      all_done = false;
                    }
                    else if(head_sessions->receiver != NULL && head_sessions->receiver->session_finished == false) {
                      all_done = false;
                    }
                    else {
                      free(head_sessions->sender);
                      if(head_sessions->receiver) {
                        free(head_sessions->receiver);
                      }
                    }
                    
                    struct session *temp = head_sessions;
                    head_sessions = head_sessions->next;
                    free(temp);
                  }
                  if(all_done) {
                    if(curr_socket->handler != NULL) {
                      curr_socket->handler((rudp_socket_t)file, RUDP_EVENT_CLOSED, &sender);
                      event_fd_delete(receive_callback, (rudp_socket_t)file);
                      close(file);
                      free(curr_socket);
                    }
                  }
                }
              }
              else {
                /* FIN received with incorrect sequence number - ignore it */
              }
            }
          }
        }
      }
    }
  }

  free(received_packet);
  return 0;
}
コード例 #8
0
/*  The server waits for client to send its initial sequence number,
 send its own initial sequence number,
 and returns the client's initial sequence number. */
uint16_t handshake(int sockfd, struct sockaddr_in &clientaddr, socklen_t clientlen)
{
    unsigned char handshake_buf[HEADERSIZE];
    segment syn, ack;
    
    // receive syn
    long recv_len;
    if ((recv_len = recvfrom(sockfd, handshake_buf, HEADERSIZE, 0,
                             (struct sockaddr *) &clientaddr, &clientlen)) < 8)
    {
        cerr << "syn error" << endl;
        return USHRT_MAX;
    }

    syn.decode(handshake_buf, HEADERSIZE);
    if (syn.getFlagsyn())
    {
        server_seq = server_ack = seq_rand(MAX_SEQ_NUM);

        bool firstSyn = true;
        do {// send syn-ack
            segment synack;
            synack.setSeqnum(server_seq);
            setReplyAck(syn, synack, 1);
            client_ack = synack.getAcknum();
            synack.setFlagsyn();
            synack.setFlagack();
            
            unsigned char *handshake_buf2 = synack.encode(NULL, 0);
            sendto(sockfd, handshake_buf2, HEADERSIZE, 0,
                   (struct sockaddr *) &clientaddr, clientlen);
            
            if (firstSyn)
            {
                cout << "Sending packet " << server_seq << " " << cwnd << " " << ssthresh
                << " SYN" << endl;
                firstSyn = false;
            }
            else
            {
                cout << "Sending packet " << server_seq << " " << cwnd << " " << ssthresh
                << " Retransmission SYN" << endl;
            }
            
            clock_t clock_begin, clock_end;
            clock_begin = clock_end = clock();
            double elapsed_secs = 0.0;
            
            // receive ack
            while ((recv_len = recvfrom(sockfd, handshake_buf, HEADERSIZE, MSG_DONTWAIT,
                                        (struct sockaddr *) &clientaddr, &clientlen)) == -1)
            {
                if (errno != EWOULDBLOCK && errno != EAGAIN)
                    perror("recvfrom");
                clock_end = clock();
                elapsed_secs = double(clock_end - clock_begin) / CLOCKS_PER_SEC;
                if (elapsed_secs >= timeout)
                    break;
            }
            if (elapsed_secs < timeout)
            {
                ack.decode(handshake_buf, HEADERSIZE);
                if (ack.getFlagsyn())
                    continue;
                else
                    break;
            }
            
        } while (true);
        
        server_seq = (server_seq + 1) % MAX_SEQ_NUM;
        
        if (ack.getFlagack() && ack.getAcknum() == server_seq)
        {
            cout << "Receiving packet " << ack.getAcknum() << endl;
            
            server_ack = ack.getAcknum();
            return client_ack;
        }
        else
        {
            cout << "ACK flag: " << ack.getFlagack() << endl;
            cout << "SYN flag: " << ack.getFlagsyn() << endl;
            cout << "ack num received: " << ack.getAcknum() << endl;
            cout << "global_seq: " << server_seq << endl;
            cerr << "ack flag error or acknum error" << endl;
            return USHRT_MAX;
        }
    }
    else
    {
        cerr << "syn flag error" << endl;
        return USHRT_MAX;
    }
}
コード例 #9
0
ファイル: misc.c プロジェクト: michaelfung/miniupdate
/* return -1 and set myip to empty string if failed to get it */
int get_myip(char *myip) {

	/* define local static variables */
	static unsigned char tries = 0;
	//static unsigned char timeout = 1;
	static int myip_sockfd;
	static struct hostent *myip_server_ent;
	static struct sockaddr_in myip_servaddr;
	static char data[] = "\n";
	static char tmpip[IPADDR_LEN];
	static ssize_t n;	/* TODO: may use a global var */
	//static struct sigaction action;
	static struct timeval tv;  /* TODO: may use a global var */

	/* init vars */
	tries = 0;
	tv.tv_sec = MYIP_TIMEOUT;
	tv.tv_usec = 0;
	bzero(tmpip, IPADDR_LEN);
	// bzero(myip, IPADDR_LEN);
	*myip = '\0';
	bzero(&myip_servaddr, sizeof(myip_servaddr));
	myip_servaddr.sin_family = AF_INET;
	myip_servaddr.sin_port = htons(myip_server_port);


	/* initialise signal handler
	bzero(&action, sizeof(action));
	action.sa_handler = timed_out;
	action.sa_flags = 0;
	sigaction(SIGALRM, &action, 0); */

	/* get IP of myip_server, and setup myip_servaddr */
	myip_server_ent = gethostbyname(myip_server);
	if (myip_server_ent == NULL) {
		logwrite("get_myip: Error resolving myip_server!");
		return(-1);
	}
	memcpy(&myip_servaddr.sin_addr.s_addr, myip_server_ent->h_addr_list[0], myip_server_ent->h_length);

	myip_sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	setsockopt(myip_sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));

	/* try a few times to read myip */
	while (tries < MAX_MYIP_TRIES) {
		sendto(myip_sockfd, data, 1, 0, (SA *)&myip_servaddr, sizeof(myip_servaddr));
		//alarm(MYIP_TIMEOUT);
		if((n = recvfrom(myip_sockfd, tmpip, IPADDR_LEN, 0, NULL, NULL)) <= 0) {
			if (log_verbose) logwrite("get_myip: Timeout reading myip_server");
			++tries;
		} else {
			chomp(tmpip);
			if (log_verbose) {
				sprintf(msg, "get_myip: %s", tmpip);
				logwrite(msg);
			}
			break;  /* got answer packet */
		}
	}

	//alarm(0);
	close(myip_sockfd);

	/* make sure tmpip is in correct format */
	if (sscanf(tmpip, "%u.%u.%u.%u", &int_tmp,&int_tmp,&int_tmp,&int_tmp) != 4) {
		return(-1);
	} else {
		strncpy(myip, tmpip, IPADDR_LEN);
		return(0);
	}
}
コード例 #10
0
ファイル: rpc2amb.c プロジェクト: EQ4/DSTK
int main(int argc,char** argv) {
// vars
// loops
int paramloop;
int loop;

// some miscellaneous vars:
int ret;

// verboselevel
int verboselevel;

// active modules
int modactive[3];

// vars for source and destination ipaddresses and ports
char *s_ipaddress, *d_ipaddress;
int s_port, d_port, d_portincr;
struct in_addr myaddr_bin;
char * myipaddress;

// vars related to receiving data
unsigned char receivebuffer[ETHERNETMTU];
int packetsize;
int udp_packetsize;
int dstar_data_len;

// vars to process streams
int packetsequence;
int direction;
int streamid;
int streamid_instream;

// vars related to sending data
unsigned char sendbuffer[ETHERNETMTU];
struct sockaddr_in6 MulticastOutAddr;

// vars to deal with DSTK frames
dstkheader_str * dstkhead_in, *dstkhead_out;
void * dstkdata;

// dealing with IP, UDP and DSTAR headers
struct iphdr * iphead;
struct udphdr * udphead;
struct dstar_rpc_header * dstar_rpc_head;
unsigned char * dstardata;

struct dstar_dv_rf_header * dv_rf_header;
struct dstar_dv_header * dv_header;
struct dstar_dv_data * dv_data;
uint8_t this_sequence;

char thismodule_c;
int thismodule_i;

int activestatus[3];
int activedirection[3];
u_short activestreamid[3];

// networking vars
int sock_in, sock_out;


// vars for timed interrupts
struct sigaction sa;
struct sigevent sev;
timer_t timerid;
struct itimerspec its;

// ////// data definition done ///


// main program starts here ///
// part 1: initialise vars and check cli-arguments

verboselevel=0;
s_ipaddress=default_s_ipaddress; s_port=default_s_port;
d_ipaddress=default_d_ipaddress; d_port=default_d_port;
d_portincr=default_d_portincr;
myipaddress=default_myipaddress;

modactive[0]=0; modactive[1]=0; modactive[2]=0;

activestatus[0]=0; activestatus[1]=0;activestatus[2]=0;

global.inbound_timeout[0]=0; global.inbound_timeout[1]=0; 
global.inbound_timeout[2]=0; 

// CLI option decoding
// format: rpc2amb [-v ] [-myip ipaddress] [-si ipaddress ] [-sp port] [-di ipaddress] [-dp port ] [-dpi portincease] module ... [module]

for (paramloop=1;paramloop<argc;paramloop++) {
	char * thisarg=argv[paramloop];

	if (strcmp(thisarg,"-V") == 0) {
		// -V = version
		fprintf(stderr,"%s version %s\n",argv[0],VERSION);
		exit(0);
	} else if (strcmp(thisarg,"-h") == 0) {
		// -h = help
		help(argv[0]);
		exit(0);
	} else if (strcmp(thisarg,"-v") == 0) {
		// -v = verbose
		verboselevel++;
	} else if (strcmp(thisarg,"-myip") == 0) {
		// -myip = my ipaddress on interface facing RPC
		if (paramloop+1 < argc) {
			paramloop++;
			myipaddress=argv[paramloop];
		}; // end if
	} else if (strcmp(thisarg,"-si") == 0) {
		// -si = SOURCE ipaddress
		if (paramloop+1 < argc) {
			paramloop++;
			s_ipaddress=argv[paramloop];
		}; // end if
	} else if (strcmp(thisarg,"-sp") == 0) {
		// -si = SOURCE port
		if (paramloop+1 < argc) {
			paramloop++;
			s_port=atoi(argv[paramloop]);
		}; // end if
	} else if (strcmp(thisarg,"-di") == 0) {
		// -di = DESTINATION ipaddress
		if (paramloop+1 < argc) {
			paramloop++;
			d_ipaddress=argv[paramloop];
		}; // end if
	} else if (strcmp(thisarg,"-dp") == 0) {
		// -dp = DESTINATION port
		if (paramloop+1 < argc) {
			paramloop++;
			d_port=atoi(argv[paramloop]);
		}; // end if
	} else if (strcmp(thisarg,"-dpi") == 0) {
		// -dp = DESTINATION port increase
		if (paramloop+1 < argc) {
			paramloop++;
			d_portincr=atoi(argv[paramloop]);
		}; // end if
	} else {
		// modules: can be 'a' up to 'c'
		if ((thisarg[0] == 'a') || (thisarg[0] == 'A')) {
			modactive[0]=1;
		} else if ((thisarg[0] == 'b') || (thisarg[0] == 'B')) {
			modactive[1]=1;
		} else if ((thisarg[0] == 'c') || (thisarg[0] == 'C')) {
			modactive[2]=1;
		} else {
			fprintf(stderr,"Warning: unknown module %c\n",thisarg[0]);
			usage(argv[0]);
		}; // end elsif (...) - if
	}; // end elsif - elsif - elsif - if
}; // end for


// we should have at least one active module
if (!(modactive[0] | modactive[1] | modactive[2])) {
	fprintf(stderr,"Error: At least one active module expected! \n");
	usage(argv[0]);
	exit(-1);
}; // end if

// main program stats here:

// start timed functions

// establing handler for signal 
sa.sa_flags = 0;
sa.sa_handler = funct_heartbeat;
sigemptyset(&sa.sa_mask);

ret=sigaction(SIGRTMIN, &sa, NULL);
if (ret <0) {
	fprintf(stderr,"Error in sigaction!\n");
	exit(-1);
}; // end if

/* Create the timer */
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIGRTMIN;
sev.sigev_value.sival_ptr = &timerid;

ret=timer_create(CLOCKID, &sev, &timerid);
if (ret < 0) {
	fprintf(stderr,"Error in timer_create!\n");
	exit(-1);
}; // end if

// start timed function, every second
its.it_value.tv_sec = 0;
its.it_value.tv_nsec = 1; // immediatly
its.it_interval.tv_sec = 1; // 1 second
its.it_interval.tv_nsec = 0;

ret=timer_settime(timerid, 0, &its, NULL);
if (ret < 0) {
	fprintf(stderr,"Error in timer_settime!\n");
	exit(-1);
}; // end if


// open inbound socket
sock_in=open_and_join_mc(s_ipaddress,s_port,verboselevel);
if (sock_in <= 0) {
	fprintf(stderr,"Error during open_and_join_mc!\n");
	exit(-1);
}; // end if

sock_out=open_for_multicast_out(verboselevel);
if (sock_out <= 0) {
	fprintf(stderr,"Error during open_for_multicast_out!\n");
	exit(-1);
}; // end if 


// convert my own ip-address into binary format
ret=inet_pton(AF_INET,myipaddress,(void *)&myaddr_bin);

// fill in fixed parts of outbound socket
MulticastOutAddr.sin6_family=AF_INET6;
MulticastOutAddr.sin6_scope_id=1;

ret=inet_pton(AF_INET6,d_ipaddress,(void *)&MulticastOutAddr.sin6_addr);
if (ret != 1) {
	fprintf(stderr,"Error: could not convert %s into valid address. Exiting\n",d_ipaddress);
	exit(1);
}; // end if


// init outbuffer
// set pointer dstkheader to beginning of buffer
dstkhead_out = (dstkheader_str *) sendbuffer;
dstkdata = (void *) sendbuffer + sizeof(dstkheader_str);

// fill in fixed parts 
dstkhead_out->version=1;

// this version of this application only contains one single DSTK-subframe
// inside one superframe. So, "last" is set to 1
dstkhead_out->flags = DSTK_FLG_LAST;


streamid=0;
packetsequence=0;

while (forever) {
	// some local vars
	int foundit;
	int giveup;
	int dstkheaderoffset;
	int thisorigin;
 	int otherfound;


	// Start receiving data from multicast stream
	// The payload of the ipv6 multicast-stream are the ipv4
	// UDP packets exchanged by the gateway-server and the
	// repeater controller	
	packetsize=recvfrom(sock_in,receivebuffer,ETHERNETMTU,0,NULL,0);

	if (packetsize == -1) {
		// no data received. Wait 2 ms and try again
		usleep(2000);
		continue;
	}; // end if

	// We should have received at least 20 octets (the size of the DSTK-header)
	if (packetsize < 20) {
		fprintf(stderr,"Packetsize to small! \n");
		continue;
	}; // end if


	// check packet: We should find a DSTK frame:
	foundit=0; giveup=0; dstkheaderoffset=0; otherfound=0;

	while ((! foundit) && (! giveup)) {
		// check DSTK packet header
		dstkhead_in = (dstkheader_str *) (receivebuffer + dstkheaderoffset);

		if (dstkhead_in->version != 1) {
			fprintf(stderr,"DSTK header version 1 expected. Got %d\n",dstkhead_in->version);
			giveup=1;
			break;
		} else if ((ntohl(dstkhead_in->type) & TYPEMASK_FILT_NOFLAGS) == TYPE_RPC_IP) {
			// OK, found Ethernet frames of RPC-stream
			foundit=1;
			break;
		};

		// OK, we found something, but it's not what we are looking for
		otherfound=1;


		// is there another subframe in the DSTK superframe?
		if ( (!(dstkhead_in->flags | DSTK_FLG_LAST))  && (dstkheaderoffset+ntohs(dstkhead_in->size)+sizeof(dstkheader_str) +sizeof(dstk_signature) <= packetsize )) {

			// not yet found, but there is a pointer to a structure further
			// on in the received packet
			// And it is still within the limits of the received packet

			// move up pointer
			dstkheaderoffset+=ntohs(dstkhead_in->size)+sizeof(dstkhead_in->size);

			// check for signature 'DSTK'
			if (memcmp(&receivebuffer[dstkheaderoffset],dstk_signature,sizeof(dstk_signature))) {
				// signature not found: give up
				giveup=1;
			} else {
				// signature found: move up pointer by 4 octets and repeat while-loop
				dstkheaderoffset += sizeof(dstk_signature);
			}; // end if                            

		} else {
			// give up
			giveup=1;
		}; // end else - elsif - elsif - if
	}; // end while

	if (giveup) {
		if (verboselevel >= 1) {
			if (otherfound) {
				fprintf(stderr,"Warning: received packet does not contain RPCIP sub-packet!\n");
			} else {
				fprintf(stderr,"Warning: received packet is not a DSTK packet!\n");
			}; // end else - if
			continue;
		}; // end if
	}; // end if

	// copy streamid
	streamid_instream=dstkhead_in->streamid1; // no need to convert
	// byte-order as we will just pass it on the outgoing stream

	// copy origin
	thisorigin=dstkhead_in->origin; // no need to convert as we just copy it to
	// from the incoming to the outgoing packets

	// sanity-check: check if the packet that has been received is large enough to
	// contain all data (error-check on overloading limits)
	// we are currently at the beginning of the DSTK header, the frame should be at least large
	// enough to hold the DATH header + the IP header + UDP header
	if (packetsize < dstkheaderoffset + sizeof(dstkheader_str) + sizeof(struct udphdr) + sizeof(struct iphdr) ) {
		if (verboselevel >= 1) {
			fprintf(stderr,"Warning: received frame is not large enough to contain DSTK_HEADER + IP header + UDP header\n");
		}; // end if
		continue;
	}; // end if


	// we should have received an ipv4 IP-packet with UDP
	iphead = (struct iphdr *) (receivebuffer + dstkheaderoffset + sizeof(dstkheader_str));

	// is it UDP?
	if (iphead->protocol != IPPROTO_UDP) {
		// not UDP
		if (verboselevel >= 1) {
			fprintf(stderr,"Warning: received packet is not a UDP packet!\n");
		}; // end if
		continue;
	}; // end if

	// Determine direction
	// if it send by me?
	ret=bcmp(&iphead->saddr, &myaddr_bin, sizeof(struct in_addr));

	if (ret == 0) {
		direction=1; // outbound
#if DEBUG > 1
fprintf(stderr,"OUTBOUND! \n");
#endif

	} else {
		// was it addressed to me?
		ret=bcmp(&iphead->daddr, &myaddr_bin, sizeof(struct in_addr));

		if (ret == 0) {
#if DEBUG > 1
fprintf(stderr,"INBOUND! \n");
#endif
			direction=0; // inbound
		} else {
			// not send by me or addressed to me. Ignore it
			if (verboselevel >= 1) {
				fprintf(stderr,"Error: received packet is not send by or addressed to me!\n");
			}; // end if
			continue;
		}; // end else - if
	}; // end else - if

	// go to UDP header, fetch length
	udphead = (struct udphdr *) (receivebuffer + dstkheaderoffset + sizeof(dstkheader_str) + sizeof(struct iphdr));

	udp_packetsize=ntohs(udphead->len) - 8; // note: udp length includes 8 bytes of the UDP header

	// sanity-check: now we know the size of the UDP-packet, we can verify if the 
	// packet that has been received is large enough to contain all data
	// (error-check on overloading limits)
	// we are currently at the beginning of the DSTK header, the frame should be at least large
	// enough to hold the DATH header + the IP header + UDP header + "udp_packet-size" of data
	if (packetsize < dstkheaderoffset + sizeof(dstkheader_str) + sizeof(struct udphdr) + sizeof(struct iphdr) + udp_packetsize ) {
		if (verboselevel >= 1) {
			fprintf(stderr,"Warning: received frame is not large enough to contain DSTK_HEADER + IP header + UDP header\n");
		}; // end if
		continue;
	}; // end if

	// go to dstar header
	dstar_rpc_head = (struct dstar_rpc_header *) (receivebuffer + dstkheaderoffset + sizeof(dstkheader_str) + sizeof(struct iphdr) + sizeof(struct udphdr) );


	// the first 4 octets of the header contain "DSTR"
	ret = strncmp("DSTR", (char *) dstar_rpc_head, 4);

	if (ret != 0) {
		// signature not found: not a star header
		if (verboselevel >= 1) {
			fprintf(stderr,"Error: received packet does not contain DSTAR signature\n");
		}; // end if
		continue;
	}; // end if

	// dive further into package
	dstar_data_len = ntohs(dstar_rpc_head->dstar_data_len);
#if DEBUG > 0
	fprintf(stderr,"dstar_data_len = %d \n",dstar_data_len);
#endif

	dstardata=(unsigned char *) (receivebuffer + dstkheaderoffset + sizeof(dstkheader_str) + sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct dstar_rpc_header) );




	// dstar_data_len can have the following values:
	// 48: first frame of DV stream
	// 19: normal frame of DV stream
	// 22: extended frame of DV stream (= normal frame + 3 octets at the end)

	// The data-transfer between the gateway-server and repeater-controller
	// happens in two phases:
	// the packet is send by one side. (rs-flag is set to 0x73)
	// after that, the reception of this packet is acknowleged by the remote
	// side (rs-flag is set to 0x72)

	// This program assumes that the exchange between the gateway-server and
	// works OK, so will just take a single-phase approach and ignore the
	// ACK messages 

	if (dstar_rpc_head->dstar_rs_flag == 0x72) {
		if (verboselevel >= 3) {
			fprintf(stderr,"RStype ACK! \n");
		}; // end if
		continue;
	}; // end if

	if (dstar_rpc_head->dstar_rs_flag != 0x73) {
		if (verboselevel >= 2) {
			fprintf(stderr,"NOT TYPE 0x73! \n");
		}; // end if
		continue;
	}; // end if


//fprintf(stderr,"dstar pkt type = %X \n",dstar_rpc_head->dstar_pkt_type);
	if (dstar_rpc_head->dstar_pkt_type != DSTAR_PKT_TYPE_DV) {
		// not a packet used for DV: ignore it
		if (verboselevel >= 2) {
			//fprintf(stderr,"Error: not a DV type packet: %X \n",dstar_rpc_head->dstar_pkt_type);
			fprintf(stderr,"NDV ");
		}; // end if
		continue;
	}; // end if


	// Check size
	if ((dstar_data_len != 19) && (dstar_data_len != 22) && (dstar_data_len != 48)) {
		if (verboselevel >= 1) {
			fprintf(stderr,"Error: Received DV packet has incorrect length: %d\n",dstar_data_len);
		}; // end if
		continue;
	}; // end if


	// set pointers to dv_header
	dv_header=(struct dstar_dv_header *) dstardata;

	// info: status: 0 = no DV stream active, 1 = stream active

#if DEBUG > 1
fprintf(stderr,"dstar_data_len = %d \n",dstar_data_len);
#endif



	// what kind of packet it is?
	// is it a start-of-stream packet
	if (dstar_data_len == 48) {
		// set pointer for rf_header
		dv_rf_header=(struct dstar_dv_rf_header *) (receivebuffer + dstkheaderoffset + sizeof(dstkheader_str) + sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct dstar_rpc_header) + sizeof(struct dstar_dv_header) );

		// determine module
		if (direction) {
			// outbound -> module is last character of rpt 2
			thismodule_c=dv_rf_header->rpt2_callsign[7];
		} else {
			// inbound -> compair with last character of rpt 1
			thismodule_c=dv_rf_header->rpt1_callsign[7];
		}; // end if

		if ((thismodule_c == 'A' || thismodule_c == 'a')) {
			thismodule_i=0; thismodule_c='A';
		} else if ((thismodule_c == 'B' || thismodule_c == 'b')) {
			thismodule_i=1; thismodule_c='B';
		} else if ((thismodule_c == 'C' || thismodule_c == 'c')) {
			thismodule_i=2; thismodule_c='C';
		} else {
			fprintf(stderr,"Warning, received stream-start packet does not have valid module-name: %c\n",thismodule_c);
			continue;
		}; // end if

		// if is a module we are interested in?
		if (! (modactive[thismodule_i])) {
			if (verboselevel >= 2) {
				fprintf(stderr,"Message, received packet for module we are not interested in: %d\n",thismodule_i);
			}; // end if
			continue;
		}; // end if

		// accept it when
		// status is 0 (no DV-stream active)
		// or when timeout (additional check to deal with
		// stale sessions where we did not receive an "end-of-stream" packet

		// the "inbound timeout" value is "armed" with 50 in this function and decreased by
		// one in the "serialsend" function. As that function is started every 20 ms, the
		// session will timeout after 1 second.

		if ((activestatus[thismodule_i] == 0) || (global.inbound_timeout[thismodule_i] == 0)) {

			// copy streamid, set frame counter, set status and go to next packet
			if (verboselevel >= 1) {
				fprintf(stderr,"NS%X/%04X \n",direction,dv_header->dv_stream_id);
			}; // end if

			activestreamid[thismodule_i]=dv_header->dv_stream_id;
			activedirection[thismodule_i]=direction;
			activestatus[thismodule_i]=1;

		} else {
			if (verboselevel >= 2) {
				//fprintf(stderr,"Error: DV header received when DV voice-frame expected\n");
				fprintf(stderr,"DVH ");
			}; // end if
			continue;
		}; // end else
	
		// frame is OK, fill in packet-type in header outgoing packet
		if (direction) {
			dstkhead_out->type=htonl(TYPE_AMB_CFG | TYPEMASK_FLG_DIR);
		} else {
			dstkhead_out->type=htonl(TYPE_AMB_CFG);
		}; // end else - if


	} else {
		// DV-data received

		// set pointer for rf_data
		dv_data=(struct dstar_dv_data *) (receivebuffer + dstkheaderoffset + sizeof(dstkheader_str) + sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct dstar_rpc_header) + sizeof(struct dstar_dv_header) );

		thismodule_i=-1;
		// determine module, based on streamid
		for (loop=0;((loop<=2) && (thismodule_i==-1));loop++) {
			if ((modactive[loop]) && (dv_header->dv_stream_id == activestreamid[loop])) {
				thismodule_i=loop;
				thismodule_c=(char) (0x41+loop);
			}; // end if
		}; // end for
			
		if (thismodule_i == -1) {
			if (verboselevel >= 2) {
//				fprintf(stderr,"Warning: received stream not linked to any active streams: %04X\n",dv_header->dv_stream_id);
				fprintf(stderr,"NAS%X/%04X ",direction,dv_header->dv_stream_id);
			}; // end if
			continue;
		};


		// is it the correct direction?
		if (direction != activedirection[thismodule_i]) {
			if (verboselevel >= 1) {
				fprintf(stderr,"Warning: Receiving stream in opposite direction for stream %04X on module %d\n",dv_header->dv_stream_id,thismodule_i);
			}; // end if
			continue;
		}; // end if


		// check sequence number: should be between 0 and 20
		this_sequence=(uint8_t) dv_data->dv_seqnr & 0x1f;

		// error check
		if (this_sequence > 20) {
			if (verboselevel >= 1) {
				fprintf(stderr,"Error: Invalid sequence number received: %d\n",this_sequence);
			}; // end if
			continue;
		}; // end if

		// last frame of stream? (6th bit set?)
		if ((uint8_t) dv_data->dv_seqnr & 0x40) {
			// set status to "off"
			activestatus[thismodule_i]=0;
fprintf(stderr,"ES%04X \n",dv_header->dv_stream_id);
		}; // end if

		// frame is OK, fill in packet-type in header outgoing packet
		if (dstar_data_len == 19) {
			// standard digital voice frame
			if (direction) {
				dstkhead_out->type=htonl(TYPE_AMB_DV | TYPEMASK_FLG_DIR);
			} else {
				dstkhead_out->type=htonl(TYPE_AMB_DV);
			}; // end else - if
		} else {
			// extended digital voice frame (length 22)
			if (direction) {
				dstkhead_out->type=htonl(TYPE_AMB_DVE | TYPEMASK_FLG_DIR);
			} else {
				dstkhead_out->type=htonl(TYPE_AMB_DVE);
			}; // end else - if
		}; // end else - if


	}; // end else - if

	
	// OK, if the packet has not been rejected by all these checkes, re-broadcast it
	// fill in rest of header
	dstkhead_out->seq1=htons(packetsequence);
	dstkhead_out->seq2=0;

	packetsequence++;
	dstkhead_out->streamid1=htons((uint32_t)dv_header->dv_stream_id);
	// streamid2 is copy of streamid1 of incoming 
	dstkhead_out->streamid2=streamid_instream;

	// origin
	dstkhead_out->origin=thisorigin;

	// copy data to dstkdata
	memcpy(dstkdata,dstardata,dstar_data_len);

	// set size
	dstkhead_out->size=htons(dstar_data_len);

	// set port
	MulticastOutAddr.sin6_port=htons((unsigned short int) d_port + thismodule_i * d_portincr);

	// copy data
	ret=sendto(sock_out,dstkhead_out,sizeof(dstkheader_str) + dstar_data_len,0,(struct sockaddr *) &MulticastOutAddr, sizeof(struct sockaddr_in6));
fprintf(stderr,"%c",thismodule_c);

	if (ret < 0) {
		fprintf(stderr,"Warning: sendto fails (error = %d(%s))\n",errno,strerror(errno));
	}; // end if
	global.inbound_timeout[thismodule_i]=3;

}; // end while (forever)


// outside "forever" loop: we should never get here unless something went wrong



return(0);

};
コード例 #11
0
int main(int argc, char **argv) {
    int sockfd; /* socket */
    int portno; /* port to listen on */
    struct sockaddr_in clientaddr; /* client addr */
    socklen_t clientlen; /* byte size of client's address */
    struct sockaddr_in serveraddr; /* server's addr */
    int optval; /* flag value for setsockopt */
    int fd;
    long file_size;
    long total_read = 0;
    unsigned char file_buf[MAX_SEQ_NUM_HALF];
    unsigned long lastbyteSent, lastbyteAcked, maxbyte;
    unsigned char *lastbyteSentPtr, *lastbyteAckedPtr, *maxbytePtr;
    clock_t clock_start, clock_end;
    bool eof = false;
    int dupAck = 0;
    map<uint16_t, clock_t> time_map;
    
    /* check command line arguments */
    if (argc != 3)
        error("Usage: ./server PORT-NUMBER FILE-NAME");
    portno = atoi(argv[1]);
    
    /* socket: create the parent socket */
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
        error("ERROR opening socket");
    
    optval = 1;
    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval , sizeof(int)) == -1){
        perror("setsockopt");
        return 1;
    };
    
    /* build the server's Internet address */
    bzero((char *) &serveraddr, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
    serveraddr.sin_port = htons((unsigned short)portno);
    
    /* bind: associate the parent socket with a port */
    if (::bind(sockfd, (struct sockaddr *) &serveraddr, sizeof(serveraddr)) == -1){
        perror("bind");
        return 2;
    }
    
    clientlen = sizeof(clientaddr);
    
    if (handshake(sockfd, clientaddr, clientlen) == USHRT_MAX)
        return 3;
    
    if ((fd = open(argv[2], O_RDONLY, 0644)) == -1){
        perror("open");
        return 4;
    }
    if ((file_size = lseek(fd, 0, SEEK_END)) == -1){
        perror("lseek");
        return 5;
    }
    if (lseek(fd, 0, SEEK_SET) == -1){
        perror("lseek");
        return 6;
    }
    
    maxbyte = lastbyteSent = lastbyteAcked = 0;
    maxbytePtr = lastbyteSentPtr = lastbyteAckedPtr = file_buf;
    clock_start = clock_end = clock();
    
    bool firstRTT = true;
    
    while (!(eof && lastbyteAcked == maxbyte))
    {
        for ( ; (lastbyteSent < maxbyte) && (unackedPackets < cwndPackets);
             (lastbyteSent += BUFSIZE) && (unackedPackets++))
        {
            segment seg;
            seg.setSeqnum(server_seq);
            int send_size;
            if ((maxbyte-lastbyteSent)/BUFSIZE >= 1)
                send_size = BUFSIZE;
            else
                send_size = (int)(maxbyte - lastbyteSent);
            
            if (lastbyteSentPtr + send_size > file_buf + MAX_SEQ_NUM_HALF)
            {
                unsigned char temp[BUFSIZE];
                long send_part2 = (lastbyteSentPtr + send_size) - (file_buf + MAX_SEQ_NUM_HALF);
                long send_part1 = send_size - send_part2;
                memcpy((char*)temp, (char*)lastbyteSentPtr, send_part1);
                memcpy((char*)(temp+send_part1), (char*)file_buf, send_part2);
                unsigned char *send_buf = seg.encode(temp, send_size);
                sendto(sockfd, send_buf, send_size+HEADERSIZE, 0, (struct sockaddr *)&clientaddr, clientlen);
                lastbyteSentPtr = lastbyteSentPtr + send_size - MAX_SEQ_NUM_HALF;
            }
            else
            {
                unsigned char *send_buf = seg.encode(lastbyteSentPtr, send_size);
                sendto(sockfd, send_buf, send_size+HEADERSIZE, 0, (struct sockaddr *)&clientaddr, clientlen);
                lastbyteSentPtr = lastbyteSentPtr + send_size;
            }
            
            clock_t now = clock();
            time_map[server_seq] = now;
            
            cout << "Sending packet " << server_seq << " " << cwnd << " " << ssthresh << endl;
            server_seq = (server_seq + send_size) % MAX_SEQ_NUM;
        }
        
        while (true)
        {
            unsigned char recv_buf[HEADERSIZE];
            long recv_len;
            if ((recv_len = recvfrom(sockfd, recv_buf, HEADERSIZE, MSG_DONTWAIT,
                                     (struct sockaddr *) &clientaddr, &clientlen)) == -1)
            {
                if (errno != EWOULDBLOCK && errno != EAGAIN)
                    perror("recvfrom");
                break;
            }
            
            segment ack;
            ack.decode(recv_buf, HEADERSIZE);
            if (ack.getFlagack())
            {
                cout << "Receiving packet " << ack.getAcknum() << endl;
                
                if (ack.getAcknum() != server_ack)
                {
                    map<uint16_t, clock_t>::iterator it = time_map.find(server_ack);
                    if (it != time_map.end())
                    {
                        clock_t now, then;
                        now = clock();
                        then = it->second;
                        time_map.erase(server_ack);
                        
                        double sampleRTT = double(now - then) / CLOCKS_PER_SEC;
                        
                        if (firstRTT)
                        {
                            estimatedRTT = sampleRTT;
                            devRTT = sampleRTT / 2;
                            adaptiveRTO = estimatedRTT + 4 * devRTT;
                            timeout = adaptiveRTO;
                            firstRTT = false;
                        }
                        else
                        {
                            double difference = sampleRTT - estimatedRTT >= 0 ?
                                                sampleRTT - estimatedRTT : estimatedRTT - sampleRTT;
                            estimatedRTT = 0.875 * estimatedRTT + 0.125 * sampleRTT;
                            devRTT = 0.75 * devRTT + 0.25 * difference;
                            adaptiveRTO = estimatedRTT + 4 * devRTT;
                            timeout = adaptiveRTO;
                        }
                    }
                    
                    uint16_t diff;
                    if (ack.getAcknum() > server_ack)
                        diff = ack.getAcknum() - server_ack;
                    else
                        diff = MAX_SEQ_NUM - server_ack + ack.getAcknum();
                    
                    lastbyteAcked += diff;
                    if (lastbyteAckedPtr + diff > file_buf + MAX_SEQ_NUM_HALF)
                        lastbyteAckedPtr = lastbyteAckedPtr + diff - MAX_SEQ_NUM_HALF;
                    else
                        lastbyteAckedPtr = lastbyteAckedPtr + diff;
                    
                    server_ack = ack.getAcknum();
                    int num_acked = diff/BUFSIZE;
                    unackedPackets -= num_acked;
                    for (int i = 0; i < num_acked; i++)
                        updateCwnd();
                    
                    clock_start = clock_end = clock();
                    dupAck = 0;
                }
                else
                {
                    if (state != FASTRECOVERY)
                    {
                        dupAck++;
                        if (dupAck == 3)
                        {
                            state = FASTRECOVERY;
                            dupAck = 0;
                            
                            ssthresh = cwnd/2 < BUFSIZE ? BUFSIZE : cwnd/2;
                            ssthreshPackets = ssthresh / BUFSIZE;
                            cwnd = ssthresh + BUFSIZE*3;
                            cwndPackets = cwnd / BUFSIZE;
                            
                            segment seg;
                            seg.setSeqnum(server_ack);
                            int send_size;
                            if ((maxbyte-lastbyteAcked)/BUFSIZE >= 1)
                                send_size = BUFSIZE;
                            else
                                send_size = (int)(maxbyte - lastbyteAcked);
                            
                            if (lastbyteAckedPtr + send_size > file_buf + MAX_SEQ_NUM_HALF)
                            {
                                unsigned char temp[BUFSIZE];
                                long send_part2 = (lastbyteAckedPtr + send_size) - (file_buf + MAX_SEQ_NUM_HALF);
                                long send_part1 = send_size - send_part2;
                                memcpy((char*)temp, (char*)lastbyteAckedPtr, send_part1);
                                memcpy((char*)(temp+send_part1), (char*)file_buf, send_part2);
                                unsigned char *send_buf = seg.encode(temp, send_size);
                                sendto(sockfd, send_buf, send_size+8, 0, (struct sockaddr *) &clientaddr, clientlen);
                            }
                            else
                            {
                                unsigned char *send_buf = seg.encode(lastbyteAckedPtr, send_size);
                                sendto(sockfd, send_buf, send_size+8, 0, (struct sockaddr *) &clientaddr, clientlen);
                            }
                            
                            cout << "Sending packet " << server_ack << " " << cwnd << " "
                            << ssthresh << " Retransmission" << endl;
                            clock_start = clock_end = clock();
                            time_map.erase(server_ack);
                        }
                    }
                    else
                    {
                        cwnd += BUFSIZE;
                        cwndPackets += 1;
                    }
                }
            }
        }
        
        clock_end = clock();
        double elapsed_secs = double(clock_end - clock_start) / CLOCKS_PER_SEC;
        if (elapsed_secs >= timeout)
        {
            state = SLOWSTART;
            dupAck = 0;
            
            ssthresh = cwnd/2 < BUFSIZE ? BUFSIZE : cwnd/2;
            ssthreshPackets = ssthresh / BUFSIZE;
            cwnd = BUFSIZE;
            cwndPackets = 1;
            
            segment seg;
            seg.setSeqnum(server_ack);
            int send_size;
            if ((maxbyte-lastbyteAcked)/BUFSIZE >= 1)
                send_size = BUFSIZE;
            else
                send_size = (int)(maxbyte - lastbyteAcked);
            
            if (lastbyteAckedPtr + send_size > file_buf + MAX_SEQ_NUM_HALF)
            {
                unsigned char temp[BUFSIZE];
                long send_part2 = (lastbyteAckedPtr + send_size) - (file_buf + MAX_SEQ_NUM_HALF);
                long send_part1 = send_size - send_part2;
                memcpy((char*)temp, (char*)lastbyteAckedPtr, send_part1);
                memcpy((char*)(temp+send_part1), (char*)file_buf, send_part2);
                unsigned char *send_buf = seg.encode(temp, send_size);
                sendto(sockfd, send_buf, send_size+8, 0, (struct sockaddr *) &clientaddr, clientlen);
            }
            else
            {
                unsigned char *send_buf = seg.encode(lastbyteAckedPtr, send_size);
                sendto(sockfd, send_buf, send_size+8, 0, (struct sockaddr *) &clientaddr, clientlen);
            }
            
            cout << "Sending packet " << server_ack << " " << cwnd << " "
            << ssthresh << " Retransmission" << endl;
            clock_start = clock_end = clock();
            
            timeout *= 2;
            time_map.erase(server_ack);
        }
        
        if (maxbyte - lastbyteAcked <= MAX_SEQ_NUM_HALF)
        {
            long bytes_left = MAX_SEQ_NUM_HALF - (maxbyte - lastbyteAcked);
            long bytes_read = 0;
            long read_len;
            if (MAX_SEQ_NUM_HALF-(maxbytePtr-file_buf) < (bytes_left))
            {
                unsigned long part1 = MAX_SEQ_NUM_HALF - (maxbytePtr - file_buf);
                unsigned long part2 = bytes_left - part1;
                read_len = read(fd, maxbytePtr, part1);
                bytes_read += read_len;
                read_len = read(fd, file_buf, part2);
                bytes_read += read_len;
            }
            else
            {
                read_len = read(fd, maxbytePtr, bytes_left);
                bytes_read += read_len;
            }
            
            maxbyte += bytes_read;
            if (maxbytePtr + bytes_read > file_buf + MAX_SEQ_NUM_HALF)
                maxbytePtr = maxbytePtr + bytes_read - MAX_SEQ_NUM_HALF;
            else
                maxbytePtr = maxbytePtr + bytes_read;
            
            total_read += bytes_read;
            if (total_read == file_size)
                eof = true;
        }
    }
    
    teardown(sockfd, clientaddr, clientlen, 0, server_seq);
    
}
コード例 #12
0
ファイル: interface_stub.c プロジェクト: smart2home/smarthome
slave_event_t slave_update(data_t *command, data_t *answer)
{
    struct timeval timeout = {
        .tv_sec = 0,
        .tv_usec = 10000
    };
    struct sockaddr_in dev_addr = {
        .sin_family = AF_INET,
        .sin_port = htons(PORT_SLAVE),
    };
    int8_t pkg[OPTIONS_NUM * sizeof(int32_t)] = {};
    int len = sizeof(pkg), addr_len = sizeof(struct sockaddr_in);
    int sockfd;
    
    if (!serialize_cb || !deserialize_cb)
        return SLAVE_INIT_ERROR;

    if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
    {
        perror("\n Error : Could not create socket \n");
        return SLAVE_NETWORK_ERROR;
    }

    if (serialize_cb(command, pkg, &dev_addr) != SLAVE_DATA)
        return SLAVE_DATA_ERROR;

#ifdef SLAVE_DEBUG_PRINT
    printf("Slave Interface Stub: Send command  to slave\n");
#endif

    if ((len = sendto(sockfd, pkg, sizeof(pkg), 0,
        (struct sockaddr *)&dev_addr, addr_len)) < 0)
    {
        perror("send");
        return SLAVE_NETWORK_ERROR;
    }
    
    if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0)
    {
        perror("Error");
        return SLAVE_NETWORK_ERROR;
    }

    if ((len = recvfrom(sockfd, pkg, sizeof(pkg), 0,
        (struct sockaddr *)&dev_addr, (socklen_t *)&addr_len)) <= 0)
    {
        perror("recv");
        return SLAVE_TIMEOUT_ERROR;
    }

#ifdef SLAVE_DEBUG_PRINT
    printf("Slave Interface Stub: Recv answer from slave\n");
#endif

    if (deserialize_cb(answer, pkg, &dev_addr) != SLAVE_DATA)
        return SLAVE_DATA_ERROR;

    return SLAVE_DATA;
}

int slave_init(slave_serialize_cb_t serialize_cb_,
    slave_deserialize_cb_t deserialize_cb_)
{
    serialize_cb = serialize_cb_;
    deserialize_cb = deserialize_cb_;
    return 0;
}
コード例 #13
0
ファイル: dns.c プロジェクト: nikosolihin/cis-654-dns-lookup
/*
 *  Perform a DNS query by sending a packet
 */
void ngethostbyname(unsigned char *host , int query_type) {
    
	unsigned char buf[65536],*qname,*reader;
	int i , j , stop , s, random_server;
	
    srand ( time(NULL) );                               // Initialize Random Seed
    random_server = rand() % dns_servercount;           // Pick a random nameserver

	struct sockaddr_in a;

	struct RES_RECORD answers[20],auth[20],addit[20];   //The replies from the DNS server
	struct sockaddr_in dest;

	struct DNS_HEADER *dns = NULL;
	struct QUESTION *qinfo = NULL;

	s = socket(AF_INET , SOCK_DGRAM , IPPROTO_UDP);     //UDP packet for DNS queries

	dest.sin_family = AF_INET;
	dest.sin_port = htons(53);
	dest.sin_addr.s_addr = inet_addr(dns_servers[random_server]); 

	// Set the DNS structure to standard queries
	dns = (struct DNS_HEADER *)&buf;

	dns->id = (unsigned short) htons(getpid());
	dns->qr = 0; 
	dns->opcode = 0; 
	dns->aa = 0; 
	dns->tc = 0; 
	dns->rd = 1; 
	dns->ra = 0; 
	dns->z = 0;
	dns->ad = 0;
	dns->cd = 0;
	dns->rcode = 0;
	dns->q_count = htons(1); 
	dns->ans_count = 0;
	dns->auth_count = 0;
	dns->add_count = 0;

	// Query Portion
	qname =(unsigned char*)&buf[sizeof(struct DNS_HEADER)];

	ChangetoDnsNameFormat(qname , host);
	qinfo =(struct QUESTION*)&buf[sizeof(struct DNS_HEADER) + (strlen((const char*)qname) + 1)];

	qinfo->qtype = htons( query_type ); 
	qinfo->qclass = htons(1); 

	printf("\nSending Packet to %s (%s) ... " , dns_servernames[random_server], dns_servers[random_server]);
	if( sendto(s,(char*)buf,sizeof(struct DNS_HEADER) + (strlen((const char*)qname)+1) + sizeof(struct QUESTION),0,(struct sockaddr*)&dest,sizeof(dest)) < 0)
	{
		perror("sendto failed");
	}
	printf("Done");

	// Receive the response
	i = sizeof dest;
	printf("\nResponse Record Received ... ");
	if(recvfrom (s,(char*)buf , 65536 , 0 , (struct sockaddr*)&dest , (socklen_t*)&i ) < 0)
	{
		perror("recvfrom failed");
	}
	printf("Done");

	dns = (struct DNS_HEADER*) buf;

	//The Query field
	reader = &buf[sizeof(struct DNS_HEADER) + (strlen((const char*)qname)+1) + sizeof(struct QUESTION)];

	printf("\nThe response contains : ");
	printf("\n\t %d Questions.",ntohs(dns->q_count));
	printf("\n\t %d Answers.",ntohs(dns->ans_count));
	printf("\n\t %d Authoritative Servers.",ntohs(dns->auth_count));
    printf("\n\t %d Additional records.\n",ntohs(dns->add_count));

	// Start Reading Answers
	stop=0;

	for(i=0;i<ntohs(dns->ans_count);i++)
	{
		answers[i].name=ReadName(reader,buf,&stop);
		reader = reader + stop;

		answers[i].resource = (struct R_DATA*)(reader);
		reader = reader + sizeof(struct R_DATA);

		if(ntohs(answers[i].resource->type) == 1)           //If it's an ipv4 address
		{
			answers[i].rdata = (unsigned char*)malloc(ntohs(answers[i].resource->data_len));

			for(j=0 ; j<ntohs(answers[i].resource->data_len) ; j++)
			{
				answers[i].rdata[j]=reader[j];
			}

			answers[i].rdata[ntohs(answers[i].resource->data_len)] = '\0';

			reader = reader + ntohs(answers[i].resource->data_len);
		}
		else
		{
			answers[i].rdata = ReadName(reader,buf,&stop);
			reader = reader + stop;
		}
	}

	// Read authorities
	for(i=0;i<ntohs(dns->auth_count);i++)
	{
		auth[i].name=ReadName(reader,buf,&stop);
		reader+=stop;

		auth[i].resource=(struct R_DATA*)(reader);
		reader+=sizeof(struct R_DATA);

		auth[i].rdata=ReadName(reader,buf,&stop);
		reader+=stop;
	}

	// Read additional
	for(i=0;i<ntohs(dns->add_count);i++)
	{
		addit[i].name=ReadName(reader,buf,&stop);
		reader+=stop;

		addit[i].resource=(struct R_DATA*)(reader);
		reader+=sizeof(struct R_DATA);

		if(ntohs(addit[i].resource->type)==1)
		{
			addit[i].rdata = (unsigned char*)malloc(ntohs(addit[i].resource->data_len));
			for(j=0;j<ntohs(addit[i].resource->data_len);j++)
			addit[i].rdata[j]=reader[j];

			addit[i].rdata[ntohs(addit[i].resource->data_len)]='\0';
			reader+=ntohs(addit[i].resource->data_len);
		}
		else
		{
			addit[i].rdata=ReadName(reader,buf,&stop);
			reader+=stop;
		}
	}

	// Print Answers
    int answer_count = ntohs(dns->ans_count);
	printf("\nAnswer Records : %d \n" , answer_count );
	for(i=0 ; i < answer_count ; i++)
	{
		printf("%s  ",answers[i].name);
        printf("%d   ",answers[i].resource->ttl);
		if( ntohs(answers[i].resource->type) == T_A)        // IPv4 address
		{
			long *p;
			p=(long*)answers[i].rdata;
			a.sin_addr.s_addr=(*p); 
			printf("IN  NS  %s",inet_ntoa(a.sin_addr));
		}

		if(ntohs(answers[i].resource->type)==5)
		{
			//CNAME for an alias
			printf("IN CNAME  %s",answers[i].rdata);
		}

		printf("\n");
	}

	// Print Authorities
	printf("\nAuthoritive Records : %d \n" , ntohs(dns->auth_count) );
	for( i=0 ; i < ntohs(dns->auth_count) ; i++)
	{
		printf("%s  ",auth[i].name);
        printf("%d  ",auth[i].resource->ttl);
		if(ntohs(auth[i].resource->type)==2)
		{
			printf("IN  NS  %s",auth[i].rdata);
		}
		printf("\n");
	}

	// Print Additional Resource Records
	dns_servercount = ntohs(dns->add_count);
	printf("\nAdditional Records : %d \n" , dns_servercount );
	for(i=0; i < dns_servercount ; i++)
	{
		printf("%s  ",addit[i].name);
		if(ntohs(addit[i].resource->type)==1)
		{
			long *p;
			p=(long*)addit[i].rdata;
			a.sin_addr.s_addr=(*p);
            const char* temp_ip = inet_ntoa(a.sin_addr);
            const char* temp_name = addit[i].name;
			printf("IN  A  %s", temp_ip);
			strcpy(dns_servers[i] , temp_ip);
			strcpy(dns_servernames[i] , temp_name);
		}
		printf("\n");
	}
	
    // Raise flag if answer records were received
    if( answer_count > 0 ) {
        done = 1;
    } else {    //information for next iteration
        printf("\nNo answer record received - Picking a nameserver above at random ...\n");
    }
}
コード例 #14
0
ファイル: ext-lpd.c プロジェクト: gema-arta/KadNode
void handle_mcast( int rc, int sock_recv ) {
	char addrbuf[FULL_ADDSTRLEN+1];
	char buf[512];
	IP c_addr;
	socklen_t addrlen;
	int rc_recv;

	if( g_mcast_time <= time_now_sec() ) {
		if( kad_count_nodes( 0 ) == 0 ) {
			/* Join multicast group if possible */
			if( g_mcast_registered == 0 && multicast_set_groups( sock_recv, &g_lpd_addr, gconf->dht_ifname, 1 ) == 0 ) {
				log_info( "LPD: No peers known. Joined multicast group." );
				g_mcast_registered = 1;
			}

			if( g_mcast_registered == 1 ) {
				log_info( "LPD: Send multicast message to find nodes." );

				/* Create message */
				snprintf(
					buf, sizeof(buf),
					msg_fmt, str_addr( &g_lpd_addr, addrbuf ),
					atoi( gconf->dht_port ), g_infohash
				);

				mcast_send_packets( buf, gconf->dht_ifname );
			}
		}

		/* Cap number of received packets to 10 per minute */
		g_packet_limit = 5 * PACKET_LIMIT_MAX;

		/* Try again in ~5 minutes */
		g_mcast_time = time_add_min( 5 );
	}

	if( rc <= 0 ) {
		return;
	}

	/* Reveice multicast ping */
	addrlen = sizeof(IP);
	rc_recv = recvfrom( sock_recv, buf, sizeof(buf), 0, (struct sockaddr*) &c_addr, (socklen_t*) &addrlen );
	if( rc_recv < 0 ) {
		log_warn( "LPD: Cannot receive multicast message: %s", strerror( errno ) );
		return;
	}

	if( g_packet_limit < 0 ) {
		/* Too much traffic - leave multicast group for now */
		if( g_mcast_registered == 1 && multicast_set_groups( sock_recv, &g_lpd_addr, gconf->dht_ifname, 0 ) == 0 ) {
			log_warn( "LPD: Too much traffic. Left multicast group." );
			g_mcast_registered = 0;
		}
		return;
	} else {
		g_packet_limit--;
	}

	if( rc_recv >= sizeof(buf) ) {
		return;
	} else {
		buf[rc_recv] = '\0';
	}

	int port = parse_packet( buf );
	if( port > 0 ) {
		port_set( &c_addr, port );
		log_debug( "LPD: Ping lonely peer at %s", str_addr( &c_addr, addrbuf ) );
		kad_ping( &c_addr );
	} else {
		log_debug( "LPD: Received invalid packet on multicast group." );
	}
}
コード例 #15
0
ファイル: ncat_listen.c プロジェクト: EliseuTorres/nmap
/* This is sufficiently different from the TCP code (wrt SSL, etc) that it
 * resides in its own simpler function
 */
static int ncat_listen_dgram(int proto)
{
    struct {
        int fd;
        union sockaddr_u addr;
    } sockfd[NUM_LISTEN_ADDRS];
    int i, fdn = -1;
    int fdmax, nbytes, n, fds_ready;
    char buf[DEFAULT_UDP_BUF_LEN] = { 0 };
    char *tempbuf = NULL;
    fd_set read_fds;
    union sockaddr_u remotess;
    socklen_t sslen = sizeof(remotess.storage);
    struct timeval tv;
    struct timeval *tvp = NULL;
    unsigned int num_sockets;

    for (i = 0; i < NUM_LISTEN_ADDRS; i++) {
        sockfd[i].fd = -1;
        sockfd[i].addr.storage.ss_family = AF_UNSPEC;
    }

    FD_ZERO(&read_fds);

    /* Initialize remotess struct so recvfrom() doesn't hit the fan.. */
    zmem(&remotess.storage, sizeof(remotess.storage));
    remotess.storage.ss_family = o.af;

#ifdef WIN32
    set_pseudo_sigchld_handler(decrease_conn_count);
#else
    /* Reap on SIGCHLD */
    Signal(SIGCHLD, sigchld_handler);
    /* Ignore the SIGPIPE that occurs when a client disconnects suddenly and we
       send data to it before noticing. */
    Signal(SIGPIPE, SIG_IGN);
#endif

    /* set for selecting udp listening sockets */
    fd_set listen_fds;
    fd_list_t listen_fdlist;
    FD_ZERO(&listen_fds);
    init_fdlist(&listen_fdlist, num_listenaddrs);

    num_sockets = 0;
    for (i = 0; i < num_listenaddrs; i++) {
        /* create the UDP listen sockets */
        sockfd[num_sockets].fd = do_listen(SOCK_DGRAM, proto, &listenaddrs[i]);
        if (sockfd[num_sockets].fd == -1) {
            if (o.debug > 0)
                logdebug("do_listen(\"%s\"): %s\n", inet_ntop_ez(&listenaddrs[i].storage, sizeof(listenaddrs[i].storage)), socket_strerror(socket_errno()));
            continue;
        }
        FD_SET(sockfd[num_sockets].fd, &listen_fds);
        add_fd(&listen_fdlist, sockfd[num_sockets].fd);
        sockfd[num_sockets].addr = listenaddrs[i];
        num_sockets++;
    }
    if (num_sockets == 0) {
        if (num_listenaddrs == 1)
            bye("Unable to open listening socket on %s: %s", inet_ntop_ez(&listenaddrs[0].storage, sizeof(listenaddrs[0].storage)), socket_strerror(socket_errno()));
        else
            bye("Unable to open any listening sockets.");
    }

    if (o.idletimeout > 0)
        tvp = &tv;

    while (1) {
        int i, j, conn_count, socket_n;

        if (fdn != -1) {
            /*remove socket descriptor which is burnt */
            FD_CLR(sockfd[fdn].fd, &listen_fds);
            rm_fd(&listen_fdlist, sockfd[fdn].fd);

            /* Rebuild the udp socket which got burnt */
            sockfd[fdn].fd = do_listen(SOCK_DGRAM, proto, &sockfd[fdn].addr);
            if (sockfd[fdn].fd == -1)
                bye("do_listen: %s", socket_strerror(socket_errno()));
            FD_SET(sockfd[fdn].fd, &listen_fds);
            add_fd(&listen_fdlist, sockfd[fdn].fd);

        }
        fdn = -1;
        socket_n = -1;
        fd_set fds;
        FD_ZERO(&fds);
        while (1) {
            /*
             * We just select to get a list of sockets which we can talk to
             */
            if (o.debug > 1)
                logdebug("selecting, fdmax %d\n", listen_fdlist.fdmax);
            fds = listen_fds;

            if (o.idletimeout > 0)
                ms_to_timeval(tvp, o.idletimeout);

            fds_ready = fselect(listen_fdlist.fdmax + 1, &fds, NULL, NULL, tvp);

            if (o.debug > 1)
                logdebug("select returned %d fds ready\n", fds_ready);

            if (fds_ready == 0)
                bye("Idle timeout expired (%d ms).", o.idletimeout);

            /*
             * Figure out which listening socket got a connection. This loop should
             * really call a function for each ready socket instead of breaking on
             * the first one.
             */
            for (i = 0; i <= listen_fdlist.fdmax && fds_ready > 0; i++) {
                /* Loop through descriptors until there is something ready */
                if (!FD_ISSET(i, &fds))
                    continue;

                /* Check each listening socket */
                for (j = 0; j < num_sockets; j++) {
                    if (i == sockfd[j].fd) {
                        if (o.debug > 1)
                            logdebug("Valid descriptor %d \n", i);
                        fdn = j;
                        socket_n = i;
                        break;
                    }
                }

                /* if we found a valid socket break */
                if (fdn != -1) {
                    fds_ready--;
                    break;
                }
            }

            /* Make sure someone connected */
            if (fdn == -1)
                continue;

            /*
             * We just peek so we can get the client connection details without
             * removing anything from the queue. Sigh.
             */
            nbytes = recvfrom(socket_n, buf, sizeof(buf), MSG_PEEK,
                              &remotess.sockaddr, &sslen);
            if (nbytes < 0) {
                loguser("%s.\n", socket_strerror(socket_errno()));
                close(socket_n);
                return 1;
            }

            /* Check conditions that might cause us to deny the connection. */
            conn_count = get_conn_count();
            if (conn_count >= o.conn_limit) {
                if (o.verbose)
                    loguser("New connection denied: connection limit reached (%d)\n", conn_count);
            } else if (!allow_access(&remotess)) {
                if (o.verbose)
                    loguser("New connection denied: not allowed\n");
            } else {
                /* Good to go. */
                break;
            }

            /* Dump the current datagram */
            nbytes = recv(socket_n, buf, sizeof(buf), 0);
            if (nbytes < 0) {
                loguser("%s.\n", socket_strerror(socket_errno()));
                close(socket_n);
                return 1;
            }
            ncat_log_recv(buf, nbytes);
        }

        if (o.debug > 1)
            logdebug("Valid Connection from %d\n", socket_n);

        conn_inc++;

        /*
         * We're using connected udp. This has the down side of only
         * being able to handle one udp client at a time
         */
        Connect(socket_n, &remotess.sockaddr, sslen);

        /* clean slate for buf */
        zmem(buf, sizeof(buf));

        /* are we executing a command? then do it */
        if (o.cmdexec) {
            struct fdinfo info = { 0 };

            info.fd = socket_n;
            if (o.keepopen)
                netrun(&info, o.cmdexec);
            else
                netexec(&info, o.cmdexec);
            continue;
        }

        FD_SET(socket_n, &read_fds);
        FD_SET(STDIN_FILENO, &read_fds);
        fdmax = socket_n;

        /* stdin -> socket and socket -> stdout */
        while (1) {
            fd_set fds;

            fds = read_fds;

            if (o.debug > 1)
                logdebug("udp select'ing\n");

            if (o.idletimeout > 0)
                ms_to_timeval(tvp, o.idletimeout);

            fds_ready = fselect(fdmax + 1, &fds, NULL, NULL, tvp);

            if (fds_ready == 0)
                bye("Idle timeout expired (%d ms).", o.idletimeout);

            if (FD_ISSET(STDIN_FILENO, &fds)) {
                nbytes = Read(STDIN_FILENO, buf, sizeof(buf));
                if (nbytes < 0) {
                    loguser("%s.\n", strerror(errno));
                    return 1;
                } else if (nbytes == 0) {
                    return 0;
                }
                if (o.crlf)
                    fix_line_endings((char *) buf, &nbytes, &tempbuf, &crlf_state);
                if (!o.recvonly) {
                    if (tempbuf != NULL)
                        n = send(socket_n, tempbuf, nbytes, 0);
                    else
                        n = send(socket_n, buf, nbytes, 0);
                    if (n < nbytes) {
                        loguser("%s.\n", socket_strerror(socket_errno()));
                        close(socket_n);
                        return 1;
                    }
                    ncat_log_send(buf, nbytes);
                }
                if (tempbuf != NULL) {
                    free(tempbuf);
                    tempbuf = NULL;
                }
            }
            if (FD_ISSET(socket_n, &fds)) {
                nbytes = recv(socket_n, buf, sizeof(buf), 0);
                if (nbytes < 0) {
                    loguser("%s.\n", socket_strerror(socket_errno()));
                    close(socket_n);
                    return 1;
                }
                ncat_log_recv(buf, nbytes);
                if (!o.sendonly)
                    Write(STDOUT_FILENO, buf, nbytes);
            }

            zmem(buf, sizeof(buf));
        }
    }

    return 0;
}
コード例 #16
0
ファイル: tftpd.c プロジェクト: juanfra684/DragonFlyBSD
int
main(int argc, char *argv[])
{
	struct tftphdr *tp;
	int n;
	int ch, on;
	struct sockaddr_storage me;
	int len;
	char *chroot_dir = NULL;
	struct passwd *nobody;
	const char *chuser = "******";

	openlog("tftpd", LOG_PID | LOG_NDELAY, LOG_FTP);
	while ((ch = getopt(argc, argv, "cClns:u:")) != -1) {
		switch (ch) {
		case 'c':
			ipchroot = 1;
			break;
		case 'C':
			ipchroot = 2;
			break;
		case 'l':
			logging = 1;
			break;
		case 'n':
			suppress_naks = 1;
			break;
		case 's':
			chroot_dir = optarg;
			break;
		case 'u':
			chuser = optarg;
			break;
		default:
			syslog(LOG_WARNING, "ignoring unknown option -%c", ch);
		}
	}
	if (optind < argc) {
		struct dirlist *dirp;

		/* Get list of directory prefixes. Skip relative pathnames. */
		for (dirp = dirs; optind < argc && dirp < &dirs[MAXDIRS];
		     optind++) {
			if (argv[optind][0] == '/') {
				dirp->name = argv[optind];
				dirp->len  = strlen(dirp->name);
				dirp++;
			}
		}
	}
	else if (chroot_dir) {
		dirs->name = "/";
		dirs->len = 1;
	}
	if (ipchroot && chroot_dir == NULL) {
		syslog(LOG_ERR, "-c requires -s");
		exit(1);
	}

	on = 1;
	if (ioctl(0, FIONBIO, &on) < 0) {
		syslog(LOG_ERR, "ioctl(FIONBIO): %m");
		exit(1);
	}
	fromlen = sizeof (from);
	n = recvfrom(0, buf, sizeof (buf), 0,
	    (struct sockaddr *)&from, &fromlen);
	if (n < 0) {
		syslog(LOG_ERR, "recvfrom: %m");
		exit(1);
	}
	/*
	 * Now that we have read the message out of the UDP
	 * socket, we fork and exit.  Thus, inetd will go back
	 * to listening to the tftp port, and the next request
	 * to come in will start up a new instance of tftpd.
	 *
	 * We do this so that inetd can run tftpd in "wait" mode.
	 * The problem with tftpd running in "nowait" mode is that
	 * inetd may get one or more successful "selects" on the
	 * tftp port before we do our receive, so more than one
	 * instance of tftpd may be started up.  Worse, if tftpd
	 * break before doing the above "recvfrom", inetd would
	 * spawn endless instances, clogging the system.
	 */
	{
		int pid;
		int i, j;

		for (i = 1; i < 20; i++) {
		    pid = fork();
		    if (pid < 0) {
				sleep(i);
				/*
				 * flush out to most recently sent request.
				 *
				 * This may drop some request, but those
				 * will be resent by the clients when
				 * they timeout.  The positive effect of
				 * this flush is to (try to) prevent more
				 * than one tftpd being started up to service
				 * a single request from a single client.
				 */
				j = sizeof from;
				i = recvfrom(0, buf, sizeof (buf), 0,
				    (struct sockaddr *)&from, &j);
				if (i > 0) {
					n = i;
					fromlen = j;
				}
		    } else {
				break;
		    }
		}
		if (pid < 0) {
			syslog(LOG_ERR, "fork: %m");
			exit(1);
		} else if (pid != 0) {
			exit(0);
		}
	}

	/*
	 * Since we exit here, we should do that only after the above
	 * recvfrom to keep inetd from constantly forking should there
	 * be a problem.  See the above comment about system clogging.
	 */
	if (chroot_dir) {
		if (ipchroot) {
			char *tempchroot;
			struct stat sb;
			int statret;
			struct sockaddr_storage ss;
			char hbuf[NI_MAXHOST];

			memcpy(&ss, &from, from.ss_len);
			unmappedaddr((struct sockaddr_in6 *)&ss);
			getnameinfo((struct sockaddr *)&ss, ss.ss_len,
				    hbuf, sizeof(hbuf), NULL, 0,
				    NI_NUMERICHOST | NI_WITHSCOPEID);
			asprintf(&tempchroot, "%s/%s", chroot_dir, hbuf);
			statret = stat(tempchroot, &sb);
			if ((sb.st_mode & S_IFDIR) &&
			    (statret == 0 || (statret == -1 && ipchroot == 1)))
				chroot_dir = tempchroot;
		}
		/* Must get this before chroot because /etc might go away */
		if ((nobody = getpwnam(chuser)) == NULL) {
			syslog(LOG_ERR, "%s: no such user", chuser);
			exit(1);
		}
		if (chroot(chroot_dir)) {
			syslog(LOG_ERR, "chroot: %s: %m", chroot_dir);
			exit(1);
		}
		chdir( "/" );
		setuid(nobody->pw_uid);
		setgroups(1, &nobody->pw_gid);
	}

	len = sizeof(me);
	if (getsockname(0, (struct sockaddr *)&me, &len) == 0) {
		switch (me.ss_family) {
		case AF_INET:
			((struct sockaddr_in *)&me)->sin_port = 0;
			break;
		case AF_INET6:
			((struct sockaddr_in6 *)&me)->sin6_port = 0;
			break;
		default:
			/* unsupported */
			break;
		}
	} else {
		memset(&me, 0, sizeof(me));
		me.ss_family = from.ss_family;
		me.ss_len = from.ss_len;
	}
	alarm(0);
	close(0);
	close(1);
	peer = socket(from.ss_family, SOCK_DGRAM, 0);
	if (peer < 0) {
		syslog(LOG_ERR, "socket: %m");
		exit(1);
	}
	if (bind(peer, (struct sockaddr *)&me, me.ss_len) < 0) {
		syslog(LOG_ERR, "bind: %m");
		exit(1);
	}
	if (connect(peer, (struct sockaddr *)&from, from.ss_len) < 0) {
		syslog(LOG_ERR, "connect: %m");
		exit(1);
	}
	tp = (struct tftphdr *)buf;
	tp->th_opcode = ntohs(tp->th_opcode);
	if (tp->th_opcode == RRQ || tp->th_opcode == WRQ)
		tftp(tp, n);
	exit(1);
}
コード例 #17
0
/* Main */
int
main(int argc, char *argv[])
{
	int					 n, detach, sock;
	socklen_t				 size;
	struct sigaction			 sa;
	struct sockaddr_hci			 addr;
	struct ng_btsocket_hci_raw_filter	 filter;
	char					 buffer[HCSECD_BUFFER_SIZE];
	ng_hci_event_pkt_t			*event = NULL;

	detach = 1;

	while ((n = getopt(argc, argv, "df:h")) != -1) {
		switch (n) {
		case 'd':
			detach = 0;
			break;

		case 'f':
			config_file = optarg;
			break;

		case 'h':
		default:
			usage();
			/* NOT REACHED */
		}
	}

	if (config_file == NULL)
		usage();
		/* NOT REACHED */

	if (getuid() != 0)
		errx(1, "** ERROR: You should run %s as privileged user!",
			HCSECD_IDENT);

	/* Set signal handlers */
	memset(&sa, 0, sizeof(sa));
	sa.sa_handler = sigint;
	sa.sa_flags = SA_NOCLDWAIT;
	if (sigaction(SIGINT, &sa, NULL) < 0)
		err(1, "Could not sigaction(SIGINT)");
	if (sigaction(SIGTERM, &sa, NULL) < 0)
		err(1, "Could not sigaction(SIGINT)");

	memset(&sa, 0, sizeof(sa));
	sa.sa_handler = sighup;
	if (sigaction(SIGHUP, &sa, NULL) < 0)
		err(1, "Could not sigaction(SIGHUP)");

	/* Open socket and set filter */
	sock = socket(PF_BLUETOOTH, SOCK_RAW, BLUETOOTH_PROTO_HCI);
	if (sock < 0)
		err(1, "Could not create HCI socket");

	memset(&filter, 0, sizeof(filter));
	bit_set(filter.event_mask, NG_HCI_EVENT_PIN_CODE_REQ - 1);
	bit_set(filter.event_mask, NG_HCI_EVENT_LINK_KEY_REQ - 1);
	bit_set(filter.event_mask, NG_HCI_EVENT_LINK_KEY_NOTIFICATION - 1);

	if (setsockopt(sock, SOL_HCI_RAW, SO_HCI_RAW_FILTER,
			(void * const) &filter, sizeof(filter)) < 0)
		err(1, "Could not set HCI socket filter");

	if (detach && daemon(0, 0) < 0)
		err(1, "Could not daemon()ize");

	openlog(HCSECD_IDENT, LOG_NDELAY|LOG_PERROR|LOG_PID, LOG_DAEMON);

	read_config_file();
	read_keys_file();

	if (detach) {
		FILE	*pid = NULL;

		if ((pid = fopen(HCSECD_PIDFILE, "w")) == NULL) {
			syslog(LOG_ERR, "Could not create PID file %s. %s (%d)",
					HCSECD_PIDFILE, strerror(errno), errno);
			exit(1);
		}

		fprintf(pid, "%d", getpid());
		fclose(pid);
	}

	event = (ng_hci_event_pkt_t *) buffer;
	while (!done) {
		size = sizeof(addr);
		n = recvfrom(sock, buffer, sizeof(buffer), 0,
				(struct sockaddr *) &addr, &size);
		if (n < 0) {
			if (errno == EINTR)
				continue;

			syslog(LOG_ERR, "Could not receive from HCI socket. " \
					"%s (%d)", strerror(errno), errno);
			exit(1);
		}

		if (event->type != NG_HCI_EVENT_PKT) {
			syslog(LOG_ERR, "Received unexpected HCI packet, " \
					"type=%#x", event->type);
			continue;
		}

		switch (event->event) {
		case NG_HCI_EVENT_PIN_CODE_REQ:
			process_pin_code_request_event(sock, &addr,
							(bdaddr_p)(event + 1));
			break;

		case NG_HCI_EVENT_LINK_KEY_REQ:
			process_link_key_request_event(sock, &addr,
							(bdaddr_p)(event + 1));
			break;

		case NG_HCI_EVENT_LINK_KEY_NOTIFICATION:
			process_link_key_notification_event(sock, &addr,
				(ng_hci_link_key_notification_ep *)(event + 1));
			break;

		default:
			syslog(LOG_ERR, "Received unexpected HCI event, " \
					"event=%#x", event->event);
			break;
		}
	}

	if (detach)
		if (remove(HCSECD_PIDFILE) < 0)
			syslog(LOG_ERR, "Could not remove PID file %s. %s (%d)",
					HCSECD_PIDFILE, strerror(errno), errno);

	dump_keys_file();
	clean_config();
	closelog();
	close(sock);

	return (0);
}
コード例 #18
0
int UDPReceive::receive( char *buffer, int len, char *tag, double *ptime ) {
	struct sockaddr_in si_other;
    int slen=sizeof(si_other);
	//socklen_t slen=sizeof(si_other);

	RTHeader_t *pheader = (RTHeader_t*)recbuffer;
	
	bool goon=true;
	int bytes = 0;
	int packetnum=-1;
	int fragments=-1;
	int fragnum=-1;
	int nextfrag=1;
	
	while( goon ) {
		int ret=0;
		
		if( !leftover ) {
			ret = recvfrom(sock, recbuffer, 65000, 0,(sockaddr*) &si_other, &slen);
		}
		leftover=false;
		
		//printf("%s UDP Packet %ld Size %d Fragment %d of %d Nextfrag %d\n", tag, pheader->packetnum, ret, pheader->fragnum, pheader->fragments, nextfrag );
		
		if( ret>sizeof( RTHeader_t ) ) {
			if( packetnum==-1 ) {						//first fragment of the new packet
				packetnum = pheader->packetnum;
			}
			
			if( packetnum != pheader->packetnum ) {		//last fragments lost
				printf("Last Frag %d lost", nextfrag );
				leftover = true;
				return -1;
			}

			//printf("%s UDP Packet %ld Size %d Fragment %d of %d Nextfrag %d\n", tag, pheader->packetnum, ret, pheader->fragnum, pheader->fragments, nextfrag );

			if( nextfrag!= pheader->fragnum ) {			//a fragment is missing
				printf("Fragment %d lost\n", nextfrag );
				return -1;
			}
			nextfrag++;
			
			memcpy( buffer+bytes, recbuffer + sizeof( RTHeader_t), ret - sizeof(RTHeader_t) );
			bytes += ret - sizeof( RTHeader_t );
			
			if(pheader->fragments == pheader->fragnum) goon=false;		//last fragment
			
			packetnum = pheader->packetnum;
			fragments = pheader->fragments;
			fragnum   = pheader->fragnum;
			
			*ptime = pheader->time;
			
		} else {
			printf("Fragment %d not larger than %d", pheader->fragnum, sizeof( RTHeader_t ) );
			return -1;
		}
		
	}
	
	leftover = false;
	return bytes;
}
コード例 #19
0
ファイル: ETHInterface_linux.c プロジェクト: John4782/cjdns
static Iface_DEFUN sendMessage(struct Message* msg, struct Iface* iface)
{
    struct ETHInterface_pvt* ctx =
        Identity_containerOf(iface, struct ETHInterface_pvt, pub.generic.iface);

    struct Sockaddr* sa = (struct Sockaddr*) msg->bytes;
    Assert_true(msg->length >= Sockaddr_OVERHEAD);
    Assert_true(sa->addrLen <= ETHInterface_Sockaddr_SIZE);

    struct ETHInterface_Sockaddr sockaddr = { .generic = { .addrLen = 0 } };
    Message_pop(msg, &sockaddr, sa->addrLen, NULL);

    struct sockaddr_ll addr;
    Bits_memcpyConst(&addr, &ctx->addrBase, sizeof(struct sockaddr_ll));

    if (sockaddr.generic.flags & Sockaddr_flags_BCAST) {
        Bits_memset(addr.sll_addr, 0xff, 6);
    } else {
        Bits_memcpyConst(addr.sll_addr, sockaddr.mac, 6);
    }

    struct ETHInterface_Header hdr = {
        .version = ETHInterface_CURRENT_VERSION,
        .zero = 0,
        .length_be = Endian_hostToBigEndian16(msg->length + ETHInterface_Header_SIZE),
        .fc00_be = Endian_hostToBigEndian16(0xfc00)
    };
    Message_push(msg, &hdr, ETHInterface_Header_SIZE, NULL);
    sendMessageInternal(msg, &addr, ctx);
    return NULL;
}

static void handleEvent2(struct ETHInterface_pvt* context, struct Allocator* messageAlloc)
{
    struct Message* msg = Message_new(MAX_PACKET_SIZE, PADDING, messageAlloc);

    struct sockaddr_ll addr;
    uint32_t addrLen = sizeof(struct sockaddr_ll);

    // Knock it out of alignment by 2 bytes so that it will be
    // aligned when the idAndPadding is shifted off.
    Message_shift(msg, 2, NULL);

    int rc = recvfrom(context->socket,
                      msg->bytes,
                      msg->length,
                      0,
                      (struct sockaddr*) &addr,
                      &addrLen);

    if (rc < ETHInterface_Header_SIZE) {
        Log_debug(context->logger, "Failed to receive eth frame");
        return;
    }

    Assert_true(msg->length >= rc);
    msg->length = rc;

    //Assert_true(addrLen == SOCKADDR_LL_LEN);

    struct ETHInterface_Header hdr;
    Message_pop(msg, &hdr, ETHInterface_Header_SIZE, NULL);

    // here we could put a switch statement to handle different versions differently.
    if (hdr.version != ETHInterface_CURRENT_VERSION) {
        Log_debug(context->logger, "DROP unknown version");
        return;
    }

    uint16_t reportedLength = Endian_bigEndianToHost16(hdr.length_be);
    reportedLength -= ETHInterface_Header_SIZE;
    if (msg->length != reportedLength) {
        if (msg->length < reportedLength) {
            Log_debug(context->logger, "DROP size field is larger than frame");
            return;
        }
        msg->length = reportedLength;
    }
    if (hdr.fc00_be != Endian_hostToBigEndian16(0xfc00)) {
        Log_debug(context->logger, "DROP bad magic");
        return;
    }

    struct ETHInterface_Sockaddr  sockaddr = { .zero = 0 };
    Bits_memcpyConst(sockaddr.mac, addr.sll_addr, 6);
    sockaddr.generic.addrLen = ETHInterface_Sockaddr_SIZE;
    if (addr.sll_pkttype == PACKET_BROADCAST) {
        sockaddr.generic.flags |= Sockaddr_flags_BCAST;
    }

    Message_push(msg, &sockaddr, ETHInterface_Sockaddr_SIZE, NULL);

    Assert_true(!((uintptr_t)msg->bytes % 4) && "Alignment fault");

    Iface_send(&context->pub.generic.iface, msg);
}

static void handleEvent(void* vcontext)
{
    struct ETHInterface_pvt* context = Identity_check((struct ETHInterface_pvt*) vcontext);
    struct Allocator* messageAlloc = Allocator_child(context->pub.generic.alloc);
    handleEvent2(context, messageAlloc);
    Allocator_free(messageAlloc);
}

List* ETHInterface_listDevices(struct Allocator* alloc, struct Except* eh)
{
    struct ifaddrs* ifaddr = NULL;
    if (getifaddrs(&ifaddr) || ifaddr == NULL) {
        Except_throw(eh, "getifaddrs() -> errno:%d [%s]", errno, strerror(errno));
    }
    List* out = List_new(alloc);
    for (struct ifaddrs* ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
        if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_PACKET) {
            List_addString(out, String_new(ifa->ifa_name, alloc), alloc);
        }
    }
    freeifaddrs(ifaddr);
    return out;
}

static int closeSocket(struct Allocator_OnFreeJob* j)
{
    struct ETHInterface_pvt* ctx = Identity_check((struct ETHInterface_pvt*) j->userData);
    close(ctx->socket);
    return 0;
}

struct ETHInterface* ETHInterface_new(struct EventBase* eventBase,
                                      const char* bindDevice,
                                      struct Allocator* alloc,
                                      struct Except* exHandler,
                                      struct Log* logger)
{
    struct ETHInterface_pvt* ctx = Allocator_calloc(alloc, sizeof(struct ETHInterface_pvt), 1);
    Identity_set(ctx);
    ctx->pub.generic.iface.send = sendMessage;
    ctx->pub.generic.alloc = alloc;
    ctx->logger = logger;

    struct ifreq ifr = { .ifr_ifindex = 0 };

    ctx->socket = socket(AF_PACKET, SOCK_DGRAM, Ethernet_TYPE_CJDNS);
    if (ctx->socket == -1) {
        Except_throw(exHandler, "call to socket() failed. [%s]", strerror(errno));
    }
    Allocator_onFree(alloc, closeSocket, ctx);

    CString_strncpy(ifr.ifr_name, bindDevice, IFNAMSIZ - 1);
    ctx->ifName = String_new(bindDevice, alloc);

    if (ioctl(ctx->socket, SIOCGIFINDEX, &ifr) == -1) {
        Except_throw(exHandler, "failed to find interface index [%s]", strerror(errno));
    }
    ctx->ifindex = ifr.ifr_ifindex;

    if (ioctl(ctx->socket, SIOCGIFFLAGS, &ifr) < 0) {
        Except_throw(exHandler, "ioctl(SIOCGIFFLAGS) [%s]", strerror(errno));
    }
    if (!((ifr.ifr_flags & IFF_UP) && (ifr.ifr_flags & IFF_RUNNING))) {
        Log_info(logger, "Bringing up interface [%s]", ifr.ifr_name);
        ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
        if (ioctl(ctx->socket, SIOCSIFFLAGS, &ifr) < 0) {
            Except_throw(exHandler, "ioctl(SIOCSIFFLAGS) [%s]", strerror(errno));
        }
    }

    ctx->addrBase = (struct sockaddr_ll) {
        .sll_family = AF_PACKET,
        .sll_protocol = Ethernet_TYPE_CJDNS,
        .sll_ifindex = ctx->ifindex,
        .sll_hatype = ARPHRD_ETHER,
        .sll_pkttype = PACKET_OTHERHOST,
        .sll_halen = ETH_ALEN
    };

    if (bind(ctx->socket, (struct sockaddr*) &ctx->addrBase, sizeof(struct sockaddr_ll))) {
        Except_throw(exHandler, "call to bind() failed [%s]", strerror(errno));
    }

    Socket_makeNonBlocking(ctx->socket);

    Event_socketRead(handleEvent, ctx, ctx->socket, eventBase, alloc, exHandler);

    return &ctx->pub;
}
コード例 #20
0
int main() {

	SOCKET wsocket;
	
	struct sockaddr_in server;
	struct sockaddr_in secondary_input;

	int slen;
	int recv_len;

	char _buffer[BUFLEN];
	WSADATA wsa;

	slen = sizeof(secondary_input);

	// initialize socket
	printf("%s\n", "Initializing dear system sequence...");

	if(WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
		printf("%s%s\n", "ERR", "winsock failure initializing. Rejecting telemetry.");
		return WSAGetLastError();
	}

	printf("%s", "Winsock initialized...\n");

	// create socket
	if(wsocket = socket(AF_INET, SOCK_DGRAM, 0) == INVALID_SOCKET) {
		printf("%s%s\n", "ERR", "winsock failure spawning. Rejecting telemetry.");
		return WSAGetLastError();
	}

	printf("%s", "Winsock spawned. Binding...");

	// set struct properties
	server.sin_family = AF_INET;
	server.sin_addr.s_addr = INADDR_ANY;
	server.sin_port = htons(PORT);

	// bind socket
	if(bind(wsocket, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR) {
		printf("%s%s\n", "ERR", "winsock failure binding. Rejecting telemetry.");
		return WSAGetLastError();
	}

	printf("%s", "winsock ready. Listening for telemetry...\n");

	while(1) {

		fflush(stdout);
		memset(_buffer, '\0', BUFLEN);

		// receive data
		if((recv_len = recvfrom(wsocket, _buffer, BUFLEN, 0, (struct sockaddr *)&secondary_input, &slen)) == SOCKET_ERROR) {
			printf("%s\n", "winsock failure receiving telemetry. Flushing...");
			return WSAGetLastError();
		}

		// print data
		printf("%s\n", _buffer);

	}

	closesocket(wsocket);
	WSACleanup();

	return 0;
}
コード例 #21
0
ファイル: socket_utility.c プロジェクト: qiaolei-qql/root
int recv_data2(int fd,char * buffer,int buffer_len, struct sockaddr* from, socklen_t* fromlen)
{
	return recvfrom(fd, buffer, buffer_len, 0, from, fromlen);
}
コード例 #22
0
ファイル: udp_engine.cpp プロジェクト: 5igm4/libzmq
void zmq::udp_engine_t::in_event()
{
  struct sockaddr_in in_address;
  socklen_t in_addrlen = sizeof(sockaddr_in);
#ifdef ZMQ_HAVE_WINDOWS
    int nbytes = recvfrom(fd, (char*) in_buffer, MAX_UDP_MSG, 0, (sockaddr*) &in_address, &in_addrlen);
    const int last_error = WSAGetLastError();
    if (nbytes == SOCKET_ERROR) {
        wsa_assert(
            last_error == WSAENETDOWN ||
            last_error == WSAENETRESET ||
            last_error == WSAEWOULDBLOCK);
        return;
    }
#else
    int nbytes = recvfrom(fd, in_buffer, MAX_UDP_MSG, 0, (sockaddr*) &in_address, &in_addrlen);
    if (nbytes == -1) {
        errno_assert(errno != EBADF
            && errno != EFAULT
            && errno != ENOMEM
            && errno != ENOTSOCK);
        return;
    }
#endif
    int rc;
    int body_size;
    int body_offset;
    msg_t msg;

    if (options.raw_socket) {
        sockaddr_to_msg (&msg, &in_address);

        body_size = nbytes;
        body_offset = 0;
    }
    else {
        char* group_buffer = (char *)in_buffer + 1;
        int group_size = in_buffer[0];

        rc = msg.init_size (group_size);
        errno_assert (rc == 0);
        msg.set_flags (msg_t::more);
        memcpy (msg.data (), group_buffer, group_size);

        //  This doesn't fit, just ingore
        if (nbytes - 1 < group_size)
            return;

        body_size = nbytes - 1 - group_size;
        body_offset = 1 + group_size;
    }

    rc = session->push_msg (&msg);
    errno_assert (rc == 0 || (rc == -1 && errno == EAGAIN));

    //  Pipe is full
    if (rc != 0) {
        rc = msg.close ();
        errno_assert (rc == 0);

        reset_pollin (handle);
        return;
    }

    rc = msg.close ();
    errno_assert (rc == 0);
    rc = msg.init_size (body_size);
    errno_assert (rc == 0);
    memcpy (msg.data (), in_buffer + body_offset, body_size);
    rc = session->push_msg (&msg);
    errno_assert (rc == 0);
    rc = msg.close ();
    errno_assert (rc == 0);
    session->flush ();
}
コード例 #23
0
ファイル: udp-recv.c プロジェクト: 09zwcbupt/personal
int
main(int argc, char **argv)
{
	struct sockaddr_in myaddr;	/* our address */
	struct sockaddr_in remaddr;	/* remote address */
	socklen_t addrlen = sizeof(remaddr);		/* length of addresses */
	int recvlen;			/* # bytes received */
	int fd;				/* our socket */
	int msgcnt = 0;			/* count # of messages we received */
	unsigned char buf[BUFSIZE];	/* receive buffer */


	/* create a UDP socket */

	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
		perror("cannot create socket\n");
		return 0;
	}

	/* bind the socket to any valid IP address and a specific port */

	memset((char *)&myaddr, 0, sizeof(myaddr));
	myaddr.sin_family = AF_INET;
	myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	myaddr.sin_port = htons(SERVICE_PORT);

	if (bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
		perror("bind failed");
		return 0;
	}

	/* now loop, receiving data and printing what we received */
        int count = 0;
        int flag = 1;
        int i;
    	struct timeval start, end;
	printf("waiting on port %d\n", SERVICE_PORT);
	for (i = 0; i < 50000; i++) {
		//printf("waiting on port %d\n", SERVICE_PORT);
		recvlen = recvfrom(fd, buf, BUFSIZE, 0, (struct sockaddr *)&remaddr, &addrlen);
		if (recvlen > 0) {
                        if (flag){
 				flag = 0;
				gettimeofday(&start, NULL);
   			}
			buf[recvlen] = 0;
                        count+=recvlen;
			//printf("received message: \"%s\" (%d bytes) from %s\n", buf, recvlen, inet_ntoa(remaddr.sin_addr));
		}
		else
			printf("uh oh - something went wrong!\n");
		/*sprintf(buf, "ack %d", msgcnt++);
		printf("sending response \"%s\"\n", buf);
		if (sendto(fd, buf, strlen(buf), 0, (struct sockaddr *)&remaddr, addrlen) < 0)
			perror("sendto");*/
	}
	gettimeofday(&end, NULL);
	double startm = (start.tv_sec) * 1000 + (start.tv_usec) / 1000 ; 
	double endm = (end.tv_sec) * 1000 + (end.tv_usec) / 1000 ; 
        double diff = endm - startm;
        printf("size: %d\ntime: %lf\nspeed: %lf KBps\n", count, diff, (count/1024)/(diff/1000));
        printf("speed: %lf Mbps\n", ((count*8)/(1024*1024))/(diff/1000));
	/* never exits */
}
コード例 #24
0
ファイル: client_stub.c プロジェクト: Lylali07/RPC
/**
 * Makes a remote procedure call on the specific server.
 */
return_type make_remote_call(const char *servernameorip,
                                const int serverportnumber,
                                const char *procedure_name,
                                const int nparams, ...) {

    return_type rt;
		rt.return_val = NULL;
		rt.return_size = 0;

    // Create server address
    struct sockaddr_in server_socket_address;
    memset((char *)&server_socket_address, 0, sizeof(server_socket_address));
    server_socket_address.sin_port = htons(serverportnumber);
    server_socket_address.sin_family = AF_INET;

    // Lookup the server's IP using the hostname provided
    struct hostent *server_ip_address;
    server_ip_address = gethostbyname(servernameorip);
    memcpy((void *)&server_socket_address.sin_addr, server_ip_address->h_addr_list[0],
        server_ip_address->h_length);

    // Create client socket and bind address to it
    int client_socket = socket(AF_INET, SOCK_DGRAM, 0);
    struct sockaddr_in client_socket_address;
    memset((char *)&client_socket_address, 0, sizeof(client_socket_address));
    client_socket_address.sin_addr.s_addr = htonl(INADDR_ANY);
    client_socket_address.sin_family = AF_INET;
    client_socket_address.sin_port = htons(client_port);
    bind(client_socket, (struct sockaddr *)&client_socket_address, sizeof(client_socket_address));

    /**
     * Pack data into buffer
     *
     * Buffer serialization format:
     * [functionSize | functionName]
     * [argumentSize | argument]
     * [argumentSize | argument]
     */

    unsigned char buffer[buffer_size];
    memset(buffer, 0, sizeof(buffer));

    // Pack function name and size in buffer
    int function_name_size = strlen(procedure_name) + 1;
    unsigned char *serial_result = int_serialize(buffer, function_name_size);
    unsigned char *function_name = (unsigned char*)procedure_name;

    int i = 0;
    while (i < function_name_size) {
        serial_result[i] = function_name[i];
        i++;
    }

    serial_result = serial_result + function_name_size;
    serial_result = int_serialize(serial_result, nparams);

    // Pack argument size and argument in buffer
    va_list var_args;
    va_start(var_args, nparams);
    i = 0;

    while (i < nparams) {
        // Put argument size in buffer
        int arg_size = va_arg(var_args, int);
        serial_result = int_serialize(serial_result, arg_size);

        // Put argument in buffer
        void *arg = va_arg(var_args, void *);
        unsigned char *char_arg = (unsigned char*)arg;

        int j = 0;
        while (j < arg_size) {
            serial_result[j] = char_arg[j];
            j++;
        }

        serial_result = serial_result + arg_size;
        i++;
    }

    va_end(var_args);

    /**
     * Make remote procedure call
     */
     sendto(client_socket, buffer, buffer_size, 0,
     (struct sockaddr *)&server_socket_address, sizeof(server_socket_address));

    /**
     * Listen for the result of remote procedure call
     */
     struct sockaddr_in remote_address;
     socklen_t addrlen = sizeof(remote_address);

     unsigned char receive_buffer[buffer_size];
     while (1) {
         int receive_length = recvfrom(client_socket, (void *)receive_buffer, buffer_size,
                0, (struct sockaddr *)&remote_address, &addrlen);

         if (receive_length > 0) {
             // Got a good message! Woot!
             unsigned char *return_value_buffer = receive_buffer + 4;
             int return_size = *(int*)receive_buffer;
             unsigned char return_value[return_size];

             int k = 0;
             while (k < return_size) {
                 return_value[k] = return_value_buffer[k];
                 k++;
             }

             memset((unsigned char *)&rt, 0, sizeof(rt));
             rt.return_val = return_value;
             rt.return_size = return_size;
             return rt;
        }
    }
}
コード例 #25
0
void* Working(void* arg)
{
    int r,i,chk,sock_id;
    char buf[BUFSIZE];
//    InitWorkServer();
#ifdef TCP
    int id;
    id=*((int*)arg);
#endif
#ifdef UDP
    sock_id=socket(AF_INET,SOCK_DGRAM,0);
    struct sockaddr_in my_addr,cl_addr;
    int y=1;
    my_addr.sin_addr=((struct sockaddr_in*)arg)->sin_addr;
    my_addr.sin_family=((struct sockaddr_in*)arg)->sin_family;
    my_addr.sin_port=((struct sockaddr_in*)arg)->sin_port;
    setsockopt(sock_id, SOL_SOCKET, SO_REUSEADDR, &y, sizeof(int));
    chk=bind(sock_id,(struct sockaddr*)&my_addr,sizeof(struct sockaddr_in));
    if(chk<0)
        perror("bind srv\n");
    socklen_t len;
    len=sizeof(struct sockaddr_in);
    printf("my port is %d\n",ntohs(my_addr.sin_port));
#endif


    while(1)
    {
#ifdef TCP
        chk=recv(id,buf,BUFSIZE*sizeof(char),0);
#endif
#ifdef UDP
        chk=recvfrom(sock_id,buf,BUFSIZE*sizeof(char),0,(struct sockaddr*)&cl_addr,&len);
#endif
        if(chk==-1)
        {
            perror("receive\n");
            continue;
        }
        else
        {
            r=rand()%2;
            if(r)
            {
                for(i=0;i<BUFSIZE;i++)
                {
                    if(buf[i]>='a'&&buf[i]<='z')
                        buf[i]-=32;
                }
            }
            else
            {
                for(i=0;i<BUFSIZE;i++)
                {
                    if(buf[i]>='A'&&buf[i]<='Z')
                        buf[i]+=32;
                }
            }
#ifdef TCP
            chk=send(id,buf,BUFSIZE*sizeof(char),0);
            if(chk==-1)
            {
                perror("send\n");
                continue;
            }
#endif
#ifdef UDP
            chk=sendto(sock_id,buf,BUFSIZE*sizeof(char),0,(struct sockaddr*)&cl_addr,len);
            if(chk==-1)
            {
                perror("send\n");
                continue;
            }
#endif
            printf("send %s\n",buf);
        }
    }
}
コード例 #26
0
int escuchaCliente(int socket, struct sockaddr_in addr)
{

    char buffer[BUFFERSIZE];
    char aux[BUFFERSIZE];
    int bytecount;
    int fin=0;
    int code=0;         /* Código de salida por defecto */
    time_t t;
    struct tm *tmp;
    socklen_t slen=sizeof(addr);
    while (!fin)
      {

    memset(buffer, 0, BUFFERSIZE);


       if((bytecount=recvfrom(socket,buffer,BUFFERSIZE,0,(struct sockaddr*)&addr,&slen))==-1)
       {
       error(5, "No puedo recibir información");
         }
printf("%s\n",buffer);
    /* Evaluamos los comandos */
    /* El sistema de gestión de comandos es muy rudimentario, pero nos vale */
    /* Comando TIME - Da la hora */
    if (strncmp(buffer, "TIME", 4)==0)
      {
        memset(buffer, 0, BUFFERSIZE);

        t = time(NULL);
        tmp = localtime(&t);
        strftime(buffer, BUFFERSIZE, "%Y-%m-%d %H:%M:%S", tmp);
      }
    
    /* Comando EXIT - Cierra la conexión actual */
    else if (strncmp(buffer, "EXIT", 4)==0)
      {
        memset(buffer, 0, BUFFERSIZE);
        sprintf(buffer, "Hasta luego. Vuelve pronto %s\n", inet_ntoa(addr.sin_addr));
        fin=1;
      }
    /* Comando CERRAR - Cierra el servidor */
    else if (strncmp(buffer, "CERRAR", 6)==0)
      {
        memset(buffer, 0, BUFFERSIZE);
        sprintf(buffer, "Adiós. Cierro el servidor\n");
        fin=1;
        code=99;        /* Salir del programa */
      }
    else
      {     
        sprintf(aux, "ECHO: %s\n", buffer);
        strcpy(buffer, aux);
      }

     if(bytecount = sendto(socket,buffer,strlen(buffer),0, (struct sockaddr*)&addr, sizeof(addr))==-1){
          error(6, "No puedo enviar información");
     }
}
 
    close(socket);
    return code;
}
コード例 #27
0
ファイル: helper.c プロジェクト: Gelma/DCC_for_Jonas
/* ask a helper process to do some filtering */
u_char					/* 1=got an answer */
ask_helper(DCC_CLNT_CTXT *ctxt, void *logp,
	   time_t avail_us,		/* spend at most this much time */
	   HELPER_REQ_HDR *req,		/* request sent to helper */
	   int req_len,
	   HELPER_RESP_HDR *resp,	/* put answer here */
	   int resp_len)
{
	DCC_EMSG emsg;
	DCC_SOCKU send_su;
	socklen_t su_len;
	DCC_SOCKU recv_su;
	char sustr[DCC_SU2STR_SIZE];
	char sustr2[DCC_SU2STR_SIZE];
	u_char counted;
	u_int gen;
	struct timeval now;
	time_t us;
	DCC_POLLFD pollfd;
	int i;

	emsg[0] = '\0';

	/* We will use the client context socket to talk to the helper,
	 * so ensure that it is open */
	if (!helper_soc_open(emsg, ctxt)) {
		thr_trace_msg(logp, "DNSBL reopen %s", emsg);
		return 0;
	}

	/* keep the lock until we have sent our request and wake-up call
	 * to ensure that some other thread does not shut down all of
	 * the helpers. */
	helper_lock();
	gettimeofday(&now, 0);

	/* If it has been a long time since we used a helper, then the last
	 * of them might be about to die of boredom.  Fix that race by
	 * restarting all of them.
	 * Most dying helpers should be reaped by the totals timer thread. */
	if (helper.idle_helpers > 0
	    && DCC_IS_TIME(now.tv_sec, helper.idle_restart,
			   HELPER_IDLE_RESTART)) {
		reap_helpers(1);
		if (helper.idle_helpers > 0)
			terminate_helpers();
		gettimeofday(&now, 0);
	}

	/* Restart all helpers if the current helper socket is the wrong
	 * family.  This should happen only when the DCC client library
	 * has chosen a new server */
	if (helper.soc != INVALID_SOCKET
	    && ctxt->soc[0].loc.sa.sa_family != AF_UNSPEC
	    && helper.su.sa.sa_family != ctxt->soc[0].loc.sa.sa_family) {
		terminate_helpers();
		gettimeofday(&now, 0);
	}

	helper.idle_restart = now.tv_sec + HELPER_IDLE_RESTART;

	if (helper.idle_helpers - helper.slow_helpers > 0) {
		/* avoid taking the last idle helper because there are
		 * usually fewer truly idle helpers than we think because
		 * we don't always wait for them to finish */
		if (helper.idle_helpers > 2
		    || helper.total_helpers >= helper.max_helpers
		    || !new_helper(ctxt, logp, req->id))
			--helper.idle_helpers;
		counted = 1;
	} else if (helper.total_helpers >= helper.max_helpers) {
		if (helper.debug > 0)
			thr_trace_msg(logp, "%s DNSBL %d idle, %d slow, and"
				      " %d total DNSBL helpers", req->id,
				      helper.idle_helpers, helper.slow_helpers,
				      helper.total_helpers);
		counted = 0;
	} else {
		if (!new_helper(ctxt, logp, req->id)) {
			helper_unlock();
			return 0;
		}
		counted = 1;
	}

	 /* The resolution of the BIND timeout limits is seconds, so even on
	  * systems where the timeout limits work, the helper might delay
	  * a second or two.  To keep the count of idle helpers as accurate
	  * as possible, always wait at least 1 second for an answer
	  * and 2 seconds for an answer to reach the parent. */
	req->avail_us = avail_us;
	avail_us += DCC_US;
	req->start = now;
	req->magic = HELPER_MAGIC_REQ;
	req->version = HELPER_VERSION;

	req->sn = ++helper.sn;
	gen = helper.gen;

	/* snapshot the address in case another thread restarts the helpers */
	send_su = helper.su;

	/* If the client context socket is connected but not to the helper
	 * socket,
	 * then either disconnect it or connect to the helper's socket */
	if (ctxt->soc[0].rem.sa.sa_family != AF_UNSPEC
	    && !DCC_SU_EQ(&ctxt->soc[0].rem, &send_su)
	    && !helper_soc_connect(emsg, ctxt, &send_su)) {
		thr_trace_msg(logp, "DNSBL soc_connect(): %s", emsg);
		help_finish(gen, 0, counted, 1);
		helper_unlock();
		return 0;
	}
	if (ctxt->soc[0].rem.sa.sa_family == AF_UNSPEC) {
		i = sendto(ctxt->soc[0].s, req, req_len, 0,
			   &send_su.sa, DCC_SU_LEN(&send_su));
	} else {
		i = send(ctxt->soc[0].s, req, req_len, 0);
	}
	if (i != req_len) {
		if (i < 0)
			thr_trace_msg(logp, "%s DNSBL sendto(%s): %s",
				      req->id, dcc_su2str(sustr, sizeof(sustr),
							&send_su),
				      ERROR_STR());
		else
			thr_trace_msg(logp, "%s DNSBL sendto(%s)=%d",
				      req->id, dcc_su2str(sustr, sizeof(sustr),
							&send_su),
				      i);
		help_finish(gen, 0, counted, 1);
		helper_unlock();
		return 0;
	}

	/* awaken a helper */
	i = write(helper.pipe_write, "x", 1);
	if (i != 1) {
		if (i < 0)
			thr_trace_msg(logp, "%s DNSBL write(pipe_write=%d): %s",
				      req->id, helper.pipe_write, ERROR_STR());
		else
			thr_trace_msg(logp, "%s DNSBL write(pipe_write)=%d",
				      req->id, i);
		help_finish(gen, 0, counted, 1);
		helper_unlock();
		return 0;
	}
	helper_unlock();

	for (;;) {
		us = avail_us - tv_diff2us(&now, &req->start);
		if (us < 0)
			us = 0;
		pollfd.fd = ctxt->soc[0].s;
		i = select_poll(emsg, &pollfd, 1, 1, us);
		if (i < 0) {
			thr_error_msg(logp, "%s DNSBL %s", req->id, emsg);
			help_finish(gen, 0, counted, 0);
			return 0;
		}
		gettimeofday(&now, 0);

		if (i == 0) {
			if (helper.debug)
				thr_trace_msg(logp,
					      "%s DNSBL no helper answer after"
					      " %1.f sec", req->id,
					      tv_diff2us(&now, &req->start)
					      / (DCC_US*1.0));
			helper_lock();
			if (helper.slow_helpers<=helper.total_helpers/MAX_SLOW)
				++helper.slow_helpers;
			help_finish(gen, 0, counted, 1);
			helper_unlock();
			return 0;
		}


		su_len = sizeof(recv_su);
		i = recvfrom(ctxt->soc[0].s, resp, resp_len,
			     0, &recv_su.sa, &su_len);
		/* because we are using UDP, we might get stray packets */
		if (i != resp_len) {
			if (i < 0) {
				thr_trace_msg(logp, "%s DNSBL recvfrom(): %s",
					      req->id, ERROR_STR());
				if (DCC_BLOCK_ERROR())
					continue;
				help_finish(gen, 0, counted, 0);
				return 0;
			}
			if (helper.debug > 1)
				thr_trace_msg(logp, "%s DNSBL recvfrom(%s)=%d",
					      req->id,
					      dcc_su2str(sustr, sizeof(sustr),
							&recv_su),
					      i);
			continue;
		}
		if (!DCC_SUnP_EQ(&send_su, &recv_su)) {
			if (helper.debug != 0)
				thr_trace_msg(logp, "%s DNSBL recvfrom(%s)"
					      " instead of %s",
					      req->id,
					      dcc_su2str(sustr, sizeof(sustr),
							&recv_su),
					      dcc_su2str(sustr2, sizeof(sustr2),
							&send_su));
			continue;
		}
		if (resp->magic != HELPER_MAGIC_RESP
		    || resp->version != HELPER_VERSION
		    || resp->sn != req->sn) {
			if (helper.debug >1 )
				thr_trace_msg(logp, "%s DNSBL recvfrom(%s)"
					      " magic=%#08x sn=%d",
					      req->id,
					      dcc_su2str(sustr, sizeof(sustr),
							&recv_su),
					      resp->magic, resp->sn);
			continue;
		}

		if (helper.debug > 4)
			thr_trace_msg(logp,"%s DNSBL answer from %s",
				      req->id,
				      dcc_su2str(sustr, sizeof(sustr),
						 &recv_su));

		help_finish(gen, 1, counted, 0);
		return 1;
	}
}
コード例 #28
0
ファイル: Pinger.cpp プロジェクト: BackupTheBerlios/nextemf
PingStatus Pinger::PingUDP(uint32 lAddr, uint32 ttl, bool doLog) {
	// UDPing reworked ping sequence -->
	int nTTL = ttl;
	int nRet;
	sockaddr_in sa;
	int nAddrLen = sizeof(struct sockaddr_in); 
	char bufICMP[1500];             // allow full MTU

	// clear ICMP socket before sending UDP - not best solution, but may be needed to exclude late responses etc
	u_long bytes2read = 0;
	do {
		nRet = ioctlsocket(is, FIONREAD, &bytes2read);
		if (bytes2read > 0) {       // ignore errors here
			sa.sin_family = AF_INET;
			sa.sin_addr.s_addr = INADDR_ANY;	
			sa.sin_port = 0;

			nRet = recvfrom (is,    /* socket */ 
				(LPSTR)bufICMP,     /* buffer */ 
				1500,               /* length */ 
				0,                  /* flags  */ 
				(sockaddr*)&sa,     /* source */ 
				&nAddrLen);         /* addrlen*/

			//if (lastTimeOut) lastTimeOut--;
			//if (!lastTimeOut && toNowTimeOut) {
			//		toNowTimeOut--;
			//		if (toNowTimeOut) lastTimeOut = 3;
			//}
		}
	} while (bytes2read > 0);

	// set TTL value for UDP packet - should success with winsock 2
	// NB! take care about IP_TTL value - it's redefined in Ws2tcpip.h!
	// TODO: solve next problem correctly:
	// eMule is linking sockets functions using wsock32.lib (IP_TTL=7)
	// to use IP_TTL define, we must enforce linker to bind this function 
	// to ws2_32.lib (IP_TTL=4) (linker options: ignore wsock32.lib)
	nRet = setsockopt(us, IPPROTO_IP, IP_TTL, (char*)&nTTL, sizeof(int));
	if (nRet==SOCKET_ERROR) { 
		DWORD lastError = WSAGetLastError();
        PingStatus returnValue;
		returnValue.success = false;
		returnValue.delay = TIMEOUT;
		returnValue.error = lastError;
		//if (toNowTimeOut < 3) toNowTimeOut++;
		//	lastTimeOut = 3;
		return returnValue;
	} 

	sa.sin_family = AF_INET;
	sa.sin_addr.s_addr = lAddr;	
	sa.sin_port = htons(UDP_PORT);

	// send lonely UDP packet with almost minimal content (0 bytes is allowed too, but no data will be sent then)
	nRet = sendto(us, (LPSTR)&nTTL, 4, 0, (sockaddr*)&sa, sizeof(sa));  // send four bytes - TTL :)
    CTimeTick m_time;
    m_time.Tick();
	if (nRet==SOCKET_ERROR) { 
		DWORD lastError = WSAGetLastError();
        PingStatus returnValue;
		returnValue.success = false;
		returnValue.error = lastError;
		//if (toNowTimeOut < 3) toNowTimeOut++;
		//	lastTimeOut = 3;
		return returnValue;
	} 

	IPHeader* reply = (IPHeader*)bufICMP;

	bytes2read = 0;
	int timeoutOpt = TIMEOUT;
	bool noRcvTimeOut = false;
	nRet = setsockopt(is, SOL_SOCKET, SO_RCVTIMEO, (const char*) &timeoutOpt, sizeof(timeoutOpt));
	if (nRet==SOCKET_ERROR)
		noRcvTimeOut = true;

    float usResTime = 0.0f;
	while((usResTime += m_time.Tick()) < TIMEOUT){
		if (noRcvTimeOut){
			nRet = ioctlsocket(is, FIONREAD, &bytes2read);
			if (nRet != 0) {
				DWORD lastError = WSAGetLastError();
                PingStatus returnValue;
				returnValue.success = false;
				returnValue.delay = TIMEOUT;
				returnValue.error = lastError;
				//if (toNowTimeOut < 3) toNowTimeOut++;
				//	lastTimeOut = 3;
				return returnValue;
			}
			if (bytes2read > 0) {       // read and filter incoming ICMP

			} else {
				Sleep(1);         // share time with other threads
				continue;
			}
		}
		sa.sin_family = AF_INET;
		sa.sin_addr.s_addr = INADDR_ANY;	
		sa.sin_port = 0;
		nRet = recvfrom (is,    /* socket */ 
			(LPSTR)bufICMP,     /* buffer */ 
			1500,               /* length */ 
			0,                  /* flags  */ 
			(sockaddr*)&sa,     /* source */ 
			&nAddrLen);         /* addrlen*/ 

		usResTime += m_time.Tick();
		if (nRet==SOCKET_ERROR) { 
			DWORD lastError = WSAGetLastError();
            PingStatus returnValue;
			returnValue.success = false;
			returnValue.delay = TIMEOUT;
			returnValue.error = lastError;
			//if (toNowTimeOut < 3) toNowTimeOut++;
			//	lastTimeOut = 3;
			return returnValue;
		} 

		unsigned short header_len = reply->h_len * 4;
		ICMPHeader* icmphdr = (ICMPHeader*)(bufICMP + header_len);
		IN_ADDR stDestAddr;

		stDestAddr.s_addr = reply->source_ip;

		if (((icmphdr->type == ICMP_TTL_EXPIRE) || (icmphdr->type == ICMP_DEST_UNREACH)) &&
			(icmphdr->UDP.dest_port == htons(UDP_PORT)) && (icmphdr->hdrsent.dest_ip == lAddr)) {

            PingStatus returnValue;

            if(icmphdr->type == ICMP_TTL_EXPIRE) {
                returnValue.success = true;
			    returnValue.status = IP_TTL_EXPIRED_TRANSIT;
			    returnValue.delay = usResTime;
			    returnValue.destinationAddress = stDestAddr.s_addr;
			    returnValue.ttl = ttl;
            } else {
                returnValue.success = true;
                returnValue.status = IP_DEST_HOST_UNREACHABLE;
			    returnValue.delay = usResTime;
			    returnValue.destinationAddress = stDestAddr.s_addr;
			    returnValue.ttl = 64 - (reply->ttl & 63);
            }

			if(doLog) {
				theApp.QueueDebugLogLine(false,_T("Reply (UDP-pinger) from %s: bytes=%d time=%3.2fms TTL=%i"),
					ipstr(stDestAddr),
					nRet,
					usResTime,
					returnValue.ttl);
			}
			return returnValue;
		} else {              // verbose log filtered packets info (not seen yet...)
			//if (lastTimeOut) lastTimeOut--;
			//if (!lastTimeOut && toNowTimeOut) {
			//		toNowTimeOut--;
			//		if (toNowTimeOut) lastTimeOut = 3;
			//}
			if(doLog) {
				theApp.QueueDebugLogLine(false,_T("Filtered reply (UDP-pinger) from %s: bytes=%d time=%3.2fms TTL=%i type=%i"),
					ipstr(stDestAddr),
					nRet,
					usResTime,
					64 - (reply->ttl & 63),
					icmphdr->type);
			}
		}
	}
	//if (usResTime >= TIMEOUT) {
	//	if (toNowTimeOut < 3) toNowTimeOut++;
	//	lastTimeOut = 3;
	//}
	// UDPing reworked ping sequence end <--

    PingStatus returnValue;
	returnValue.success = false;
	returnValue.delay = TIMEOUT;
	returnValue.error = IP_REQ_TIMED_OUT;

    return returnValue;
}
コード例 #29
-1
ファイル: helper.c プロジェクト: Gelma/DCC_for_Jonas
/* helper processes start here via fork()/exec() in the parent  */
void DCC_NORET
helper_child(DCC_SOCKET s, int fd, int total_helpers)
{
	sigset_t sigs;
	socklen_t soc_len;
	DNSBL_REQ req;
	int req_len;
	DNSBL_RESP resp;
	DCC_SOCKU req_su;
	socklen_t su_len;
	struct timeval now;
	u_char wake_buf;
	int secs, i;

	/* this process inherits via exec() by dccm or dccifd odd signal
	 * blocking from some pthreads implementations including FreeBSD 5.* */
	signal(SIGHUP, SIG_IGN);
	signal(SIGINT, SIG_IGN);
	signal(SIGTERM, SIG_IGN);
	sigemptyset(&sigs);
	sigaddset(&sigs, SIGALRM);
	sigprocmask(SIG_UNBLOCK, &sigs, 0);

	helper_init(0);
	if (have_helpers)
		dcc_logbad(EX_SOFTWARE, "no threads for DNSBL helpers");

	helper.total_helpers = total_helpers;

	helper.pipe_read = fd;
	helper.soc = s;
	soc_len = sizeof(helper.su);
	if (0 > getsockname(helper.soc, &helper.su.sa, &soc_len))
		dcc_logbad(EX_IOERR, "DNSBL helper getsockname(%d): %s",
			   helper.soc, ERROR_STR());

	if (helper.debug > 1)
		dcc_trace_msg("DNSBL helper process starting on %s",
			      dcc_su2str_err(&helper.su));

	for (;;) {
		/* Use read() and SIGALRM to watch for a wake-up byte
		 * from the parent, the parent ending and closing the pipe,
		 * or enough idle time to require our retirement.  This
		 * tactic awakens a single child for each wake-up call
		 * from the parent.  Using select() or poll() on the main
		 * socket awakens a thundering herd of children */
		secs = HELPER_IDLE_STOP_SECS+1;
		if (helper.total_helpers > 0)
			secs /= helper.total_helpers+1;
		if (secs < 5)
			secs = 5;
		signal(SIGALRM, helper_alarm);
#ifdef HAVE_SIGINTERRUPT
		siginterrupt(SIGALRM, 1);
#endif
		helper_alarm_hit = 0;
		alarm(secs);
		for (;;) {
			su_len = sizeof(req_su);
			req_len = recvfrom(helper.soc, &req, ISZ(req), 0,
					   &req_su.sa, &su_len);

			/* sleep until awakened if no work is ready */
			if (req_len <= 0) {
				if (req_len == 0)
					dcc_logbad(EX_IOERR,
						   "DNSBL helper recvfrom()=0");
				if (!DCC_BLOCK_ERROR())
					dcc_logbad(EX_IOERR,
						   "DNSBL helper recvfrom():"
						   " %s",
						   ERROR_STR());
				if (helper_alarm_hit)
					helper_exit("idle helper exit");

				i = read(helper.pipe_read, &wake_buf, 1);

				/* The other end of the pipe can be marked
				 * non-blocking by some pthreads
				 * implementations.  That makes read() on this
				 * end fail with EAGAIN.  When that happens,
				 * fall back on select() or poll().
				 * Even on such pthread implementations,
				 * it rarely happens. */
				if (i < 0 && DCC_BLOCK_ERROR()) {
					DCC_POLLFD pollfd;
					DCC_EMSG emsg;

					pollfd.fd = helper.pipe_read;
					i = select_poll(emsg, &pollfd, 1,
							0, -1);
					if (i < 0)
					    dcc_logbad(EX_IOERR,
						       "dnsbl HELPER %s", emsg);
				}

				/* loof for work after a wake-up call */
				if (i > 0)
					continue;

				if (helper_alarm_hit)
					continue;
				if (i == 0)
					helper_exit("shutdown");
				if (i < 0) {
					dcc_logbad(EX_OSERR,
						   "DNSBL read(terminate): %s",
						   ERROR_STR());
				}
			}
			if (req_len != helper.req_len) {
				if (helper.debug)
					dcc_trace_msg("DNSBL helper"
						      " recvfrom(parent %s)=%d"
						      " instead of %d",
						      dcc_su2str_err(&req_su),
						      req_len,
						      helper.req_len);
				continue;
			}

			/* we might get stray packets because we cannot
			 * connect to a single port */
			if (!DCC_SUnP_EQ(&helper.su, &req_su)) {
				if (helper.debug)
					dcc_trace_msg("DNSBL helper"
						    " request from"
						    " %s instead of %s",
						    dcc_su2str_err(&req_su),
						    dcc_su2str_err(&helper.su));
				continue;
			}

			if (req.hdr.magic != HELPER_MAGIC_REQ
			    || req.hdr.version != HELPER_VERSION) {
				if (helper.debug)
					dcc_trace_msg("DNSBL helper"
						      " recvfrom(parent %s)"
						      " magic=%#08x",
						      dcc_su2str_err(&req_su),
						      req.hdr.magic);
				continue;
			}
			break;
		}
		gettimeofday(&now, 0);
		alarm(0);

		/* do not bother working if it is already too late to answer,
		 * perhaps because a previous helper died */
		i = tv_diff2us(&now, &req.hdr.start);
		if (i >= req.hdr.avail_us) {
			if (helper.debug > 1)
				dcc_trace_msg("%s DNSBL helper"
					      " already too late to start;"
					      " used %.1f of %.1f seconds",
					      req.hdr.id, i / (DCC_US*1.0),
					      req.hdr.avail_us / (DCC_US*1.0));
			continue;
		}

		memset(&resp, 0, sizeof(resp));
		resp.hdr.magic = HELPER_MAGIC_RESP;
		resp.hdr.version = HELPER_VERSION;
		resp.hdr.sn = req.hdr.sn;

		/* do the work and send an answer if we have one */
		if (!dnsbl_work(&req, &resp))
			continue;

		/* do not answer if it is too late */
		gettimeofday(&now, 0);
		i = tv_diff2us(&now, &req.hdr.start);
		if (i > (req.hdr.avail_us + DCC_US/2)) {
			if (helper.debug > 1)
				dcc_trace_msg("%s DNSBL helper"
					      " too late to answer;"
					      " used %.1f of %.1f seconds",
					      req.hdr.id, i / (DCC_US*1.0),
					      req.hdr.avail_us / (DCC_US*1.0));
			continue;
		}

		i = sendto(helper.soc, &resp, sizeof(resp), 0,
			   &req_su.sa, DCC_SU_LEN(&req_su));
		if (i != sizeof(resp)) {
			if (i < 0)
				dcc_error_msg("%s helper sendto(%s): %s",
					      req.hdr.id,
					      dcc_su2str_err(&req_su),
					      ERROR_STR());
			else
				dcc_error_msg("%s helper sendto(%s)=%d",
					      req.hdr.id,
					      dcc_su2str_err(&req_su), i);
		}
	}
}
コード例 #30
-1
/**
 * The main program
 *
 * Parameters:
 *	 - int argc  => The number of arguments passed
 *	 - char** args  => The arguments list
 *
 * Return:
 *	 - int  => The result of the execution
 */
int main(int argc, char** args) {

	/* ##### Process parameters and get filter ##### */
	int filter = process_params(argc, args);


	/* ##### Network structures ##### */
	// Initialize the client socket
	struct sockaddr_in destination;
	int client_socket = init_socket(args[1], &destination);

	// Parameters for the packet transmission
	struct packet to_server;
	struct packet from_server;
	socklen_t destination_length = (socklen_t)sizeof(struct sockaddr);


	/* ##### Audio reader parameters ##### */
	// Some more variables that we'll need for reading audio files
	int sample_rate, sample_size, channels;
	int write_init_audio = 0;


	/* ##### Timeout parameters ##### */
	int nb;
	fd_set watch_over;
	struct timeval timeout;


	/* ##### Filter parameters ##### */
	// For volume filter
	int volume_value;

	// For echo filter
	int nb_buffers_per_echo = 0, nb_samples_per_buffer, current_buffer_position, to_read_position;
	char* echo_buffer;
	char volume_buffer[BUFFER_SIZE];



	/* 	################################################## Sending the filename ################################################## */

	// The first packet to send is the filename
	create_packet(&to_server, P_FILENAME, args[2]);

	// Send the packet containing the filename
	if (sendto(client_socket, &to_server, sizeof(struct packet), 0, (struct sockaddr*)&destination, destination_length) == -1) {
		perror("Error during the sending of the filename packet");
		return 1;
	}



	/* 	################################################## Talk with the server ################################################## */
	do {

		// Clear and reinitialize the fd set
		FD_ZERO(&watch_over);
		FD_SET(client_socket, &watch_over);
		timeout.tv_sec = 0;
		timeout.tv_usec = TIMEOUT_CLIENT;  // 200ms
		nb = select(client_socket+1, &watch_over, NULL, NULL, &timeout);

		// Clear packets
		clear_packet(&to_server);
		clear_packet(&from_server);

		// If error during the select
		if (nb < 0) {
			perror("Can't attach the select to the file descriptor");
			return 1;
		}

		// Just request the same packet if timeout reached
		if (nb == 0) {
			to_server.type = P_REQ_SAME_PACKET;
			if (sendto(client_socket, &to_server, sizeof(struct packet), 0, (struct sockaddr*)&destination, destination_length) == -1) {
				perror("Can't request same packet");
				return 1;
			}
		}

		// If open, just act normally
		if (FD_ISSET(client_socket, &watch_over)) {

			// Wait a packet
			if (recvfrom(client_socket, &from_server, sizeof(struct packet), 0, (struct sockaddr*)&destination, &destination_length) != -1) {

				// In function of the type of the packet received
				switch (from_server.type) {

					// --------------- An server error happened on the server ---------------
					case P_ERR_TRANSMISSION:
					case P_SERVER_ERROR:

						// Display the error
						printf("%s\n", from_server.message);

						// Close connection
						close_connection(client_socket, "Closing due to server error", 0);
						break;


					// --------------- The first response from the server is received ---------------
					case P_FILE_HEADER:

						// Get the informations about the audio file
						sample_rate = *((int*)(from_server.message));
						sample_size = *((int*)(from_server.message + BUFFER_SPACE));
						channels = *((int*)(from_server.message + 2*BUFFER_SPACE));


						// ----- Filters initialisation -----
						switch (filter) {

							// If none do nothing
							case F_NONE:
								break;

							// If mono, just force the channel to one
							case F_MONO:
								channels = 1;
								break;

							// If volume, get the value of the filter parameter
							case F_VOLUME:
								volume_value = atoi(args[4]);
								nb_samples_per_buffer = BUFFER_SIZE/(sample_size/8);
								break;

							// If echo, allocate the echo buffer
							case F_ECHO:

								// Calculate the number of bytes needed for one second
								nb_buffers_per_echo = (ECHO_IN_SCDS * sample_rate * (sample_size/8)) / BUFFER_SIZE;

								// Allocate the table of buffers
								echo_buffer = malloc(nb_buffers_per_echo * BUFFER_SIZE);

								// The buffer position and the buffer to read put to 0
								current_buffer_position = 0;
								to_read_position = 0;
								break;

							// If speed
							case F_SPEED:

								// Multiply the framerate
								sample_rate = sample_rate * atoi(args[4]);
								break;

							// If unknown
							default:
								close_connection(client_socket, "Unknown filter", write_init_audio);
								break;
						}


						// Initialize the write end
						write_init_audio = aud_writeinit(sample_rate, sample_size, channels);

						// If an error happened
						if (write_init_audio < 1) {

							// If echo filter, free the buffer
							if (filter == F_ECHO) free(echo_buffer);

							// Close the connection
							close_connection(client_socket, "Error at getting the audio output device", 0);
						}

						// If everything's ok, request the first block
						clear_packet(&to_server);
						to_server.type = P_REQ_NEXT_BLOCK;

						// Send the request
						if (sendto(client_socket, &to_server, sizeof(struct packet), 0, (struct sockaddr*)&destination, destination_length) == -1) {
							
							// If echo filter, free the buffer
							if (filter == F_ECHO) free(echo_buffer);

							// Close the connection
							close_connection(client_socket, "Error at requesting the first block", write_init_audio);
						}

						break;


					// --------------- A block is received, read it ---------------
					case P_BLOCK:

						// Read the music on the audio output (in function of the filter passed)
						switch (filter) {

							// If none, mono or speed
							case F_NONE:
							case F_MONO:
							case F_SPEED:
								if (write(write_init_audio, from_server.message, BUFFER_SIZE) == -1)
									close_connection(client_socket, "Error at writing a block on audio output", write_init_audio);
								break;

							// If echo
							case F_ECHO:

								// Read the content of the buffer received
								if (write(write_init_audio, from_server.message, BUFFER_SIZE) == -1) {

									// Echo filter so free the buffer
									free(echo_buffer);

									// Close connection
									close_connection(client_socket, "Error at writing a block on audio output", write_init_audio);
								}

								// Then put this buffer into the echo buffer if the buffer isn't full
								if (current_buffer_position < nb_buffers_per_echo) {

									memcpy((echo_buffer + current_buffer_position*BUFFER_SIZE), from_server.message, BUFFER_SIZE);
									++current_buffer_position;
								}

								// If the echo buffer is full
								else {

									// Read the current buffer position
									if (write(write_init_audio, (echo_buffer + to_read_position*BUFFER_SIZE), BUFFER_SIZE) == -1) {

										// Echo filter so free the buffer
										free(echo_buffer);

										// Close connection
										close_connection(client_socket, "Error at writing an echo block on audio output", write_init_audio);
									}

									// And replace it with the new one
									memcpy((echo_buffer + to_read_position*BUFFER_SIZE), from_server.message, BUFFER_SIZE);

									// Increment the flag
									to_read_position = (to_read_position+1)%nb_buffers_per_echo;

								}
								break;

							// If upper or lower volume
							case F_VOLUME:

								// Clear the temporary buffer
								memset(volume_buffer, 0, BUFFER_SIZE);

								// Variables used in the loop
								int i;  // The increment var and a temporary value
								int tmp;  // Temporary var

								// Get each sample and multiply its value
								for (i = 0; i < nb_samples_per_buffer; ++i) {

									// Multiply the value of the sample, get a double value
									tmp = *((int*)(from_server.message + i*sizeof(int))) * volume_value;

									// Then store it in the temporary buffer
									*((int*)(volume_buffer + i*sizeof(int))) = tmp;
								}

								// And in the end, read the whole buffer
								if (write(write_init_audio, volume_buffer, BUFFER_SIZE) == -1)
									close_connection(client_socket, "Error at writing a volume changed block on audio output", write_init_audio);

								break;

							// If an unknown filter, error!
							default:
								close_connection(client_socket, "Filter passed unknown", write_init_audio);
								break;

						}  // End of filter's switch

						// If everything's ok, request the next block
						clear_packet(&to_server);
						to_server.type = P_REQ_NEXT_BLOCK;

						// Send the request
						if (sendto(client_socket, &to_server, sizeof(struct packet), 0, (struct sockaddr*)&destination, destination_length) == -1) {

							// If echo filter, free the buffer
							if (filter == F_ECHO) free(echo_buffer);

							// Close connection
							close_connection(client_socket, "Error at requesting a block", write_init_audio);
						}

						break;


					// --------------- The last block is received, read it ---------------
					case P_EOF:

						// Read the music on the audio output (in function of the filter passed)
						switch (filter) {

							// If none, mono or speed
							case F_NONE:
							case F_MONO:
							case F_SPEED:
								if (write(write_init_audio, from_server.message, BUFFER_SIZE) == -1)
									close_connection(client_socket, "Error at writing a block on audio output", write_init_audio);
								break;

							// If echo
							case F_ECHO:

								// Read the content of the buffer received
								if (write(write_init_audio, from_server.message, BUFFER_SIZE) == -1) {

									// Echo filter so free the buffer
									free(echo_buffer);

									// Close connection
									close_connection(client_socket, "Error at writing a block on audio output", write_init_audio);
								}

								// And in the end, just read the whole echo buffer left
								if (write(write_init_audio, (echo_buffer + to_read_position*BUFFER_SIZE), ((current_buffer_position - to_read_position)*BUFFER_SIZE)) == -1) {
									
									// Echo filter so free the buffer
									free(echo_buffer);

									// Close connection
									close_connection(client_socket, "Error at writing the last echo block on audio output", write_init_audio);
								}

								// Free the echo_buffer in the end
								free(echo_buffer);

								break;

							// If upper or lower volume
							case F_VOLUME:

								// Clear the temporary buffer
								memset(volume_buffer, 0, BUFFER_SIZE);

								// Variables used in the loop
								int i;  // The increment var and a temporary value
								int tmp;  // Temporary var

								// Get each sample and multiply its value
								for (i = 0; i < nb_samples_per_buffer; ++i) {

									// Multiply the value of the sample, get a double value
									tmp = *((int*)(from_server.message + i*sizeof(int))) * volume_value;

									// Then store it in the temporary buffer
									*((int*)(volume_buffer + i*sizeof(int))) = tmp;
								}

								// And in the end, read the whole buffer
								if (write(write_init_audio, volume_buffer, BUFFER_SIZE) == -1)
									close_connection(client_socket, "Error at writing a volume changed block on audio output", write_init_audio);

								break;

							// If an unknown filter, error!
							default:
								close_connection(client_socket, "Filter passed unknown", write_init_audio);
								break;

						}

						// If everything's ok, send the last packet
						clear_packet(&to_server);

						// Close the connection
						close_connection(client_socket, "The file was correctly read, close the connection, bye", write_init_audio);
						break;


					// --------------- Unknown type ---------------
					default:
						close_connection(client_socket, "Packet type unknown", write_init_audio);
						break;
					
				}
			}
		}

		// If an error during the receiving of a packet
		else {
									
			// If echo filter, free the buffer (only if it has been initialized)
			if ((filter == F_ECHO) && (nb_buffers_per_echo > 0)) free(echo_buffer);

			// Close connection
			perror("Error during the receiving of a packet, the server may be busy");
			return 0;
		}

	} while (from_server.type != P_CLOSE_TRANSMISSION);

	// Close the connection
	close_connection(client_socket, "The reading is done, close connection now", write_init_audio);

	// If everything's was ok (but the server is normally just waiting for clients)
	return 0;
}