示例#1
0
文件: peer.c 项目: jasonabele/connman
static void report_error_cb(void *user_context, bool retry, void *user_data)
{
	struct connman_peer *peer = user_context;

	if (retry) {
		int err;
		err = peer_connect(peer);

		if (err == 0 || err == -EINPROGRESS)
			return;
	}

	reply_pending(peer, ENOTCONN);

	peer_disconnect(peer);

	if (!peer->connection_master) {
		__connman_dhcp_stop(peer->ipconfig);
		__connman_ipconfig_disable(peer->ipconfig);
	} else
		stop_dhcp_server(peer);

	peer->connection_master = false;
	peer->sub_device = NULL;
}
示例#2
0
/**
 * Initiator - Send Connection Request.
 * Tries to connect to the remote peer's socket. If the connection is refused, the new
 * state is I_Rcv_Conn_NAck, else I_Rcv_Conn_Ack.
 * \note Must be called with a lock on the peer.
 * @param p - peer to send to
 * @returns the new state for the peer
 */
peer_state_t I_Snd_Conn_Req(peer *p)
{
	LM_INFO("I_Snd_Conn_Req(): Peer %.*s \n",
		p->fqdn.len,p->fqdn.s);

	if (p->I_sock>0) close(p->I_sock);
	p->I_sock = -1;
	p->I_sock = peer_connect(p);
	if (p->I_sock<0){
		return I_Rcv_Conn_NAck;
	}
	
	return I_Rcv_Conn_Ack;
}
示例#3
0
文件: peer.c 项目: jasonabele/connman
static DBusMessage *connect_peer(DBusConnection *conn,
					DBusMessage *msg, void *user_data)
{
	struct connman_peer *peer = user_data;
	GList *list, *start;
	int err;

	DBG("peer %p", peer);

	if (peer->pending)
		return __connman_error_in_progress(msg);

	list = g_hash_table_get_values(peers_table);
	start = list;
	for (; list; list = list->next) {
		struct connman_peer *temp = list->data;

		if (temp == peer || temp->device != peer->device)
			continue;

		if (is_connecting(temp) || is_connected(temp)) {
			if (peer_disconnect(temp) == -EINPROGRESS) {
				g_list_free(start);
				return __connman_error_in_progress(msg);
			}
		}
	}

	g_list_free(start);

	peer->pending = dbus_message_ref(msg);

	err = peer_connect(peer);
	if (err == -EINPROGRESS)
		return NULL;

	if (err < 0) {
		dbus_message_unref(peer->pending);
		peer->pending = NULL;

		return __connman_error_failed(msg, -err);
	}

	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
示例#4
0
END_TEST


START_TEST(test_peer_connect) {
  char host[100] = "127.0.0.1";
  char port[6] = TEST_PORT;
  char hostport[107];
  sprintf(hostport, "%s:%s", host, port);
  peer * p = peer_create("local", hostport);

  /* creating server for test */
  int server_sock = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP);
  struct addrinfo * ainfo, hint;
  memset(&hint, 0, sizeof(struct addrinfo));
  hint.ai_family = AF_UNSPEC;
  hint.ai_socktype = SOCK_STREAM;
  hint.ai_flags = AI_PASSIVE; /* for NULLed host */
  hint.ai_protocol = IPPROTO_TCP;
  hint.ai_canonname = NULL;
  hint.ai_addr = NULL;
  hint.ai_next = NULL;
  ck_assert_int_eq(getaddrinfo(host, port, &hint, &ainfo), 0);
  ck_assert_int_eq(bind(server_sock, ainfo->ai_addr, ainfo->ai_addrlen), 0);
  ck_assert_int_eq(listen(server_sock, 10), 0);

  ck_assert_int_eq(peer_connect(p), 0);
  int client_sock = accept(server_sock, NULL, NULL);
  char * msg = "testmsg";
  send(p->sock, msg, 8, MSG_DONTWAIT);
  char buf[25];
  recv(client_sock, buf, 8, MSG_DONTWAIT);
  ck_assert_str_eq(buf, "testmsg");

  close(p->sock);
  close(client_sock);
  close(server_sock);
}
示例#5
0
文件: dnsx.c 项目: fscz/dnsx
/* Return 0 for a request that is pending or if all slots are full, otherwise
   return the value of peer_sendreq or peer_connect respectively... */
static void request_add(struct request_t *r) {
  uint pos = r->id % MAX_REQUESTS; // XXX r->id is unchecked
  struct peer_t *dst_peer;
  unsigned short int *ul;
  time_t ct = time(NULL);
  struct request_t *req_in_table = 0;

  for (;;) {
    if (requests[pos].id == 0) {
      // this one is unused, take it
      req_in_table = &requests[pos];
      break;
    }
    else {
      if (requests[pos].id == r->id) {
        if (memcmp((char*)&r->a, (char*)&requests[pos].a, sizeof(r->a)) == 0) {
          // a request for the same id and url already exists
          // do not process the new request
          return;
        }
        else {
          // ids are same but the queried urls are different.
          // this is weird. we rather drop the package before
          // we do some black magic that blows up on us.
          // one failed ns request is not that bad.
          // clients usually repeat them anyways.
          /*
          do {
            r->id = ((rand()>>16) % 0xffff);
          } while (r->id < 1);
          pos = r->id % MAX_REQUESTS;
          //printf("NATing id (id was %d now is %d)\n", r->rid, r->id);
          continue;
          */
          log_packet(r->id, DROP_IN, UDP, REQ_IP(r), REQ_PORT(r));
          return;
        }
      }
      else if ((requests[pos].timeout + MAX_TIME) > ct) {
        // request timed out, take it               
        req_in_table = &requests[pos];
        break;
      }
      else {
        pos++;
        pos %= MAX_REQUESTS;
        if (pos == (r->id % MAX_REQUESTS)) {
          // we are at our capacities. drop the request
          log_packet(r->id, DROP_IN, UDP, REQ_IP(r), REQ_PORT(r));
          return;
        }
      }
    }
  }

  r->timeout = time(NULL); /* REFACTOR not ct? sloppy */

  // update id
  ul = (unsigned short int*)(r->b + 2);
  *ul = htons(r->id);   

  if ( req_in_table == NULL ) {
    return;
  } else {
    memcpy((char*)req_in_table, (char*)r, sizeof(*req_in_table));
  }
  
  dst_peer = peer_select();

  if (dst_peer->con == CONNECTED) {
    peer_sendreq(dst_peer, req_in_table);
  }
  else if (dst_peer->con != CONNECTING) {
    // The request will be sent by peer_handleoutstanding when the
    // connection is established. Actually (see QUASIBUG notice
    // earlier) when *any* connection is established.
    peer_connect(dst_peer, ns_select());
  } 
}
示例#6
0
int 
main(int argc, char *argv[])
{
  char c;
  fd_set rset;
  int i, err, sd, maxsd;
  struct hostent *phost;                              // the FQDN of this host
  struct sockaddr_in self;                            // the address of this host

  int npeers;
  pte_t pte[PR_MAXPEERS], redirected;                 // a 2-entry peer table
  char pnamebuf[PR_MAXPEERS*(PR_MAXFQDN+1)] = { 0 };  // space to hold 2 FQDNs 
  char *pname[PR_MAXPEERS];                           // pointers to above spaces
  pmsg_t msg;

  // init
  npeers=0;
  memset((char *) &self, 0, sizeof(struct sockaddr_in));
  for (i=0; i < PR_MAXPEERS; i++) {
    pname[i] = &pnamebuf[i*(PR_MAXFQDN+1)];
    pte[i].pte_sd = PR_UNINIT_SD;
  }
  
  // parse args, see the comments for peer_args()
  if (peer_args(argc, argv, pname[0], &pte[0].pte_peer.peer_port)) {
    peer_usage(argv[0]);
  }

#ifdef _WIN32
  WSADATA wsa;
  
  err = WSAStartup(MAKEWORD(2,2), &wsa);  // winsock 2.2
  net_assert(err, "peer: WSAStartup");
#endif
  
#ifndef _WIN32
  signal(SIGPIPE, SIG_IGN);    /* don't die if peer is dead */
#endif

  /* if pname is provided, connect to peer */
  if (*pname[0]) {

    pte[0].pte_pname = pname[0];

    /* Task 2: YOUR CODE HERE
     *
     * Given the peer whose FQDN is stored in pname[0],
     * get peer's address and stores it in the first entry
     * of the peer table (pte[0]).
    */
    struct hostent *sp;
    sp = gethostbyname(pname[0]);
    memcpy(&pte[0].pte_peer.peer_addr, sp->h_addr, sp->h_length); 
    /* connect to peer in pte[0] */
    peer_connect(pte);  // Task 2: fill in the peer_connect() function above
    /* Task 2: YOUR CODE HERE
     *
     * Upon return from peer_connect(), the socket descriptor in
     * pte[0] should have been initialized and connected to the peer.
     * Obtain the ephemeral port assigned by the OS kernel to this
     * socket and store it in the variable "self" (along with the
     * peer's address).
    */
    socklen_t len = sizeof(self);
    if(getsockname(pte[0].pte_sd, (struct sockaddr *)&self, &len) < 0)
        abort();
 
    npeers++;

    /* inform user of connection to peer */
    fprintf(stderr, "Connected to peer %s:%d\n", pname[0],
            ntohs(pte[0].pte_peer.peer_port));
  }

  /* setup and listen on connection */
  sd = peer_setup(self.sin_port);  // Task 1: fill in the peer_setup() function above
  if (!self.sin_port) {
    /* Task 1: YOUR CODE HERE
       If a peer was not provided in the command line using "-p", the
       port number will be 0 and the socket sd would have been
       assigned an ephemeral port when calling bind() in peer_setup().
       Obtain the ephemeral port and store it in the variable "self"
       (along with peer's address) by copying the same chunk of code
       you just wrote at the end of the if statement block above. */
    socklen_t len = sizeof(self);
    if (getsockname(sd, (struct sockaddr *) &self, &len) < 0) 
      abort();   
  }
  
  /* Task 1: YOUR CODE HERE
     Find out the FQDN of the current host (use pname[1] as scratch
     space to put the name). Use gethostname(), it is sufficient most
     of the time. */
  gethostname (pname[1], PR_MAXFQDN+1);
  /* inform user which port this peer is listening on */
  fprintf(stderr, "This peer address is %s:%d\n",
          pname[1], ntohs(self.sin_port));

  do {
    /* determine the largest socket descriptor */
    maxsd = (sd > pte[0].pte_sd ? sd : pte[0].pte_sd);
    if (maxsd < pte[1].pte_sd) { maxsd = pte[1].pte_sd; }

    /* set all the descriptors to select() on */
    FD_ZERO(&rset);
#ifndef _WIN32
    FD_SET(STDIN_FILENO, &rset); // wait for input from std input,
        // Winsock only works with socket and stdin is not a socket
#endif
    FD_SET(sd, &rset);           // or the listening socket,
    for (i = 0; i < PR_MAXPEERS; i++) {
      if (pte[i].pte_sd > 0) {

        FD_SET(pte[i].pte_sd, &rset);  // or the peer connected sockets
      }
    }
    
    /* Task 1: YOUR CODE HERE
       Call select() to wait for any activity on any of the above
       descriptors. */
    select(maxsd+1, &rset, NULL, NULL, NULL);

#ifndef _WIN32
    if (FD_ISSET(STDIN_FILENO, &rset)) {
      // user input: if getchar() returns EOF or if user hits q, quit,
      // else flush input and go back to waiting
      if (((c = getchar()) == EOF) || (c == 'q') || (c == 'Q')) {
        fprintf(stderr, "Bye!\n");
        break;
      }
      fflush(stdin);
    }
#endif

    if (FD_ISSET(sd, &rset)) {

      // a connection is made to this host at the listened to socket
      if (npeers < PR_MAXPEERS) {
        /* Peer table is not full.  Accept the peer, send a welcome
         * message.  if we are connected to another peer, also sends
         * back the peer's address+port#
         */
        // Task 1: fill in the functions peer_accept() and peer_ack() above
        peer_accept(sd, &pte[npeers]);
        err = peer_ack(pte[npeers].pte_sd, PM_WELCOME,
                       (npeers > 0 ? &pte[0].pte_peer : 0));

        err = (err != sizeof(pmsg_t));
        net_assert(err, "peer: peer_ack welcome");
        pte[npeers].pte_pname = pname[npeers];

        /* log connection */
        /* get the host entry info on the connected host. */
        phost = gethostbyaddr((char *) &pte[npeers].pte_peer.peer_addr,
                            sizeof(struct in_addr), AF_INET);
        strcpy(pname[npeers], 
               ((phost && phost->h_name) ? phost->h_name:
                inet_ntoa(pte[npeers].pte_peer.peer_addr)));
        
        /* inform user of new peer */
        fprintf(stderr, "Connected from peer %s:%d\n",
                pname[npeers], ntohs(pte[npeers].pte_peer.peer_port));
        
        npeers++;

      } else {
        // Peer table full.  Accept peer, send a redirect message.
        // Task 1: the functions peer_accept() and peer_ack() you wrote
        //         must work without error in this case also.
        peer_accept(sd, &redirected);
        err = peer_ack(redirected.pte_sd, PM_RDIRECT,
                       (npeers > 0 ? &pte[0].pte_peer : 0));
        err = (err != sizeof(pmsg_t));
        net_assert(err, "peer: peer_ack redirect");

        /* log connection */
        /* get the host entry info on the connected host. */
        phost = gethostbyaddr((char *) &redirected.pte_peer.peer_addr,
                            sizeof(struct in_addr), AF_INET);

        /* inform user of peer redirected */
        fprintf(stderr, "Peer table full: %s:%d redirected\n",
               ((phost && phost->h_name) ? phost->h_name:
                inet_ntoa(redirected.pte_peer.peer_addr)),
                ntohs(redirected.pte_peer.peer_port));

        /* closes connection */
        close(redirected.pte_sd);
      } 
    }

    for (i = 0; i < PR_MAXPEERS; i++) {


      if (pte[i].pte_sd > 0 && FD_ISSET(pte[i].pte_sd, &rset)) {
        // a message arrived from a connected peer, receive it
        err = peer_recv(pte[i].pte_sd, &msg); // Task 2: fill in the functions peer_recv() above
        net_assert((err < 0), "peer: peer_recv");



        if (err == 0) {
          // if connection closed by peer, reset peer table entry
          pte[i].pte_sd = PR_UNINIT_SD;
        } else {
          // if connection closed by peer, reset peer table entry
          fprintf(stderr, "Received ack from %s:%d\n", pte[i].pte_pname,
                  ntohs(pte[i].pte_peer.peer_port));
          
          if (msg.pm_vers != PM_VERS) {
            fprintf(stderr, "unknown message version.\n");
          } else {
            if (msg.pm_npeers) {
              // if message contains a peer address, inform user of
              // the peer two hops away
              phost = gethostbyaddr((char *) &msg.pm_peer.peer_addr,
                                    sizeof(struct in_addr), AF_INET);
              fprintf(stderr, "  which is peered with: %s:%d\n", 
                      ((phost && phost->h_name) ? phost->h_name :
                       inet_ntoa(msg.pm_peer.peer_addr)),
                      ntohs(msg.pm_peer.peer_port));
            }
            
            if (msg.pm_type == PM_RDIRECT) {
              // inform user if message is a redirection
              fprintf(stderr, "Join redirected, try to connect to the peer above.\n");
            } 
          }
        }
      }
    }

  } while (1);

#ifdef _WIN32
  WSACleanup();
#endif
  exit(0);
}