Changeset 38:68c1890f7049 in freeDiameter
- Timestamp:
- Nov 5, 2009, 5:29:12 PM (15 years ago)
- Branch:
- default
- Phase:
- public
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
freeDiameter/cnxctx.c
r31 r38 1144 1144 if (conn->cc_socket > 0) { 1145 1145 shutdown(conn->cc_socket, SHUT_RDWR); 1146 close(conn->cc_socket); 1147 conn->cc_socket = -1; 1146 1148 } 1147 1149 -
freeDiameter/endpoints.c
r33 r38 94 94 } 95 95 96 /* Keep only endpoints of the same family as af */ 97 int fd_ep_filter_family( struct fd_list * list, int af ) 98 { 99 struct fd_list * li; 100 101 TRACE_ENTRY("%p %d", list, af); 102 CHECK_PARAMS(list); 103 104 for (li = list->next; li != list; li = li->next) { 105 struct fd_endpoint * ep = (struct fd_endpoint *)li; 106 107 if (ep->sa.sa_family != af) { 108 li = li->prev; 109 fd_list_unlink(&ep->chain); 110 free(ep); 111 } 112 } 113 114 return 0; 115 } 116 96 117 /* Reset the given flag(s) from all items in the list */ 97 118 int fd_ep_clearflags( struct fd_list * list, uint32_t flags ) -
freeDiameter/fD.h
r37 r38 148 148 struct cnxctx * p_receiver; /* Only used in case of election */ 149 149 pthread_t p_ini_thr; 150 struct fd_list p_connparams; /* The list of connection attempts, see p_cnx.c */ 150 151 }; 151 152 … … 244 245 void fd_psm_next_timeout(struct fd_peer * peer, int add_random, int delay); 245 246 int fd_psm_change_state(struct fd_peer * peer, int new_state); 246 void fd_psm_cleanup(struct fd_peer * peer );247 void fd_psm_cleanup(struct fd_peer * peer, int terminate); 247 248 248 249 /* Peer out */ … … 250 251 int fd_out_start(struct fd_peer * peer); 251 252 int fd_out_stop(struct fd_peer * peer); 253 254 /* Initiating connections */ 255 int fd_p_cnx_init(struct fd_peer * peer); 256 void fd_p_cnx_abort(struct fd_peer * peer, int cleanup_all); 252 257 253 258 /* Peer sent requests cache */ -
freeDiameter/p_cnx.c
r37 r38 38 38 /* This file contains code used by a peer state machine to initiate a connection to remote peer */ 39 39 40 struct next_conn { 41 struct fd_list chain; 42 int proto; /* Protocol of the next attempt */ 43 sSS ss; /* The address, only for TCP */ 44 uint16_t port; /* The port, for SCTP (included in ss for TCP) */ 45 int dotls; /* Handshake TLS after connection ? */ 46 }; 47 48 static int prepare_connection_list(struct fd_peer * peer) 49 { 50 /* Resolve peer address(es) if needed */ 51 if (FD_IS_LIST_EMPTY(&peer->p_hdr.info.pi_endpoints)) { 52 struct addrinfo hints, *ai, *aip; 53 int ret; 54 55 memset(&hints, 0, sizeof(hints)); 56 hints.ai_flags = AI_ADDRCONFIG; 57 ret = getaddrinfo(peer->p_hdr.info.pi_diamid, NULL, &hints, &ai); 58 if (ret) { 59 fd_log_debug("Unable to resolve address for peer '%s' (%s), aborting this connection\n", peer->p_hdr.info.pi_diamid, gai_strerror(ret)); 60 fd_psm_terminate( peer ); 61 return 0; 62 } 63 64 for (aip = ai; aip != NULL; aip = aip->ai_next) { 65 CHECK_FCT( fd_ep_add_merge( &peer->p_hdr.info.pi_endpoints, aip->ai_addr, aip->ai_addrlen, EP_FL_DISC ) ); 66 } 67 freeaddrinfo(ai); 68 } 69 70 /* Remove addresses from unwanted family */ 71 if (peer->p_hdr.info.config.pic_flags.pro3) { 72 CHECK_FCT( fd_ep_filter_family( 73 &peer->p_hdr.info.pi_endpoints, 74 (peer->p_hdr.info.config.pic_flags.pro3 == PI_P3_IP) ? 75 AF_INET 76 : AF_INET6)); 77 } 78 79 TODO("Prepare the list in peer->p_connparams obeying the flags"); 80 81 TODO("Return an error if the list is empty in the end"); 82 83 return ENOTSUP; 84 } 85 86 static __inline__ void failed_connection_attempt(struct fd_peer * peer) 87 { 88 /* Simply remove the first item in the list */ 89 struct fd_list * li = peer->p_connparams.next; 90 fd_list_unlink(li); 91 free(li); 92 } 93 94 static void empty_connection_list(struct fd_peer * peer) 95 { 96 /* Remove all items */ 97 while (!FD_IS_LIST_EMPTY(&peer->p_connparams)) { 98 failed_connection_attempt(peer); 99 } 100 } 101 40 102 41 103 /* The thread that attempts the connection */ … … 44 106 struct fd_peer * peer = arg; 45 107 struct cnxctx * cnx = NULL; 46 47 48 49 /* Use the flags in the peer to select the protocol */ 50 51 TODO("loop on fd_cnx_cli_connect_tcp or fd_cnx_cli_connect_sctp"); 52 108 struct next_conn * nc = NULL; 109 110 TRACE_ENTRY("%p", arg); 111 CHECK_PARAMS_DO( CHECK_PEER(peer), return NULL ); 112 113 do { 114 /* Rebuild the list if needed, if it is empty */ 115 if (FD_IS_LIST_EMPTY(&peer->p_connparams)) { 116 CHECK_FCT_DO( prepare_connection_list(peer), goto fatal_error ); 117 if (FD_IS_LIST_EMPTY(&peer->p_connparams)) 118 /* Already logged and peer terminated */ 119 return NULL; 120 } 121 122 /* Attempt connection to the first entry */ 123 nc = (struct next_conn *)(peer->p_connparams.next); 124 125 switch (nc->proto) { 126 case IPPROTO_TCP: 127 cnx = fd_cnx_cli_connect_tcp((sSA *)&nc->ss, sSSlen(&nc->ss)); 128 break; 129 #ifndef DISABLE_SCTP 130 case IPPROTO_SCTP: 131 cnx = fd_cnx_cli_connect_sctp((peer->p_hdr.info.config.pic_flags.pro3 == PI_P3_IP) ?: fd_g_config->cnf_flags.no_ip6, nc->port, &peer->p_hdr.info.pi_endpoints); 132 break; 133 #endif /* DISABLE_SCTP */ 134 } 135 136 if (cnx) 137 break; 138 139 /* Pop these parameters and continue */ 140 failed_connection_attempt(peer); 141 142 pthread_testcancel(); 143 144 } while (!cnx); /* and until cancellation */ 53 145 54 146 /* Now, we have an established connection in cnx */ … … 57 149 58 150 /* Handshake if needed (secure port) */ 59 60 151 if (nc->dotls) { 152 CHECK_FCT_DO( fd_cnx_handshake(cnx, GNUTLS_CLIENT, peer->p_hdr.info.config.pic_priority, NULL), 153 { 154 /* Handshake failed ... */ 155 fd_log_debug("TLS Handshake failed with peer '%s', resetting the connection\n", peer->p_hdr.info.pi_diamid); 156 fd_cnx_destroy(cnx); 157 empty_connection_list(peer); 158 fd_ep_filter(&peer->p_hdr.info.pi_endpoints, EP_FL_CONF); 159 return NULL; 160 } ); 161 } 61 162 62 163 /* Upon success, generate FDEVP_CNX_ESTABLISHED */ 63 164 CHECK_FCT_DO( fd_event_send(peer->p_events, FDEVP_CNX_ESTABLISHED, 0, cnx), goto fatal_error ); 165 64 166 pthread_cleanup_pop(0); 65 167 66 168 return NULL; 169 67 170 fatal_error: 68 171 /* Cleanup the connection */ 69 fd_cnx_destroy(cnx); 172 if (cnx) 173 fd_cnx_destroy(cnx); 70 174 71 175 /* Generate a termination event */ … … 79 183 int fd_p_cnx_init(struct fd_peer * peer) 80 184 { 185 TRACE_ENTRY("%p", peer); 186 81 187 /* Start the connect thread */ 82 188 CHECK_FCT( pthread_create(&peer->p_ini_thr, NULL, connect_thr, peer) ); 83 189 return 0; 84 190 } 191 192 /* Cancel a connection attempt */ 193 void fd_p_cnx_abort(struct fd_peer * peer, int cleanup_all) 194 { 195 TRACE_ENTRY("%p %d", peer, cleanup_all); 196 CHECK_PARAMS_DO( CHECK_PEER(peer), return ); 197 198 if (peer->p_ini_thr != (pthread_t)NULL) { 199 CHECK_FCT_DO( fd_thr_term(&peer->p_ini_thr), /* continue */); 200 failed_connection_attempt(peer); 201 } 202 203 if (cleanup_all) { 204 empty_connection_list(peer); 205 } 206 } -
freeDiameter/p_psm.c
r37 r38 243 243 244 244 /* Cleanup the peer */ 245 void fd_psm_cleanup(struct fd_peer * peer )245 void fd_psm_cleanup(struct fd_peer * peer, int terminate) 246 246 { 247 247 /* Move to CLOSED state: failover messages, stop OUT thread, unlink peer from active list */ 248 248 CHECK_FCT_DO( fd_psm_change_state(peer, STATE_CLOSED), /* continue */ ); 249 249 250 /* Destroy data */ 251 CHECK_FCT_DO( fd_thr_term(&peer->p_ini_thr), /* continue */); 250 251 fd_p_cnx_abort(peer, terminate); 252 252 253 if (peer->p_cnxctx) { 253 254 fd_cnx_destroy(peer->p_cnxctx); 254 255 peer->p_cnxctx = NULL; 255 256 } 257 256 258 if (peer->p_initiator) { 257 259 fd_cnx_destroy(peer->p_initiator); 258 260 peer->p_initiator = NULL; 259 261 } 262 260 263 if (peer->p_receiver) { 261 264 fd_cnx_destroy(peer->p_receiver); 262 265 peer->p_receiver = NULL; 266 } 267 268 if (terminate) { 269 CHECK_FCT_DO( fd_fifo_del(&peer->p_events), /* continue */ ); 263 270 } 264 271 … … 527 534 case STATE_CLOSING: 528 535 /* Cleanup the peer */ 529 fd_psm_cleanup(peer );536 fd_psm_cleanup(peer, 0); 530 537 531 538 /* Reset the timer */ … … 602 609 case STATE_WAITCEA: 603 610 /* Destroy the connection, restart the timer to a new connection attempt */ 604 fd_psm_cleanup(peer );611 fd_psm_cleanup(peer, 0); 605 612 fd_psm_next_timeout(peer, 1, peer->p_hdr.info.config.pic_tctimer ?: fd_g_config->cnf_timer_tc); 606 613 break; … … 622 629 623 630 psm_end: 624 fd_psm_cleanup(peer); 625 CHECK_FCT_DO( fd_fifo_del(&peer->p_events), /* continue */ ); 631 fd_psm_cleanup(peer, 1); 626 632 pthread_cleanup_pop(1); /* set STATE_ZOMBIE */ 627 633 peer->p_psm = (pthread_t)NULL; … … 675 681 676 682 /* Cleanup the data */ 677 fd_psm_cleanup(peer );683 fd_psm_cleanup(peer, 1); 678 684 679 685 /* Destroy the event list */ -
freeDiameter/sctp.c
r33 r38 641 641 } 642 642 643 /* Create a client socket and connect to remote server*/644 int fd_sctp_client( int *sock, int no_ip6, uint16_t port, struct fd_list * list)643 /* Add addresses from the list that match the flags to the array */ 644 static int add_addresses_from_list_mask(uint8_t ** array, int * count, size_t * offset, uint16_t port, struct fd_list * list, uint32_t mask, uint32_t val) 645 645 { 646 int family; 647 int count = 0; 648 size_t offset = 0, sz; 646 size_t sz; 647 struct fd_list * li; 649 648 union { 650 649 uint8_t *buf; 651 sSA *sa;652 } sar;653 union {654 uint8_t *buf;655 sSA *sa;656 650 sSA4 *sin; 657 651 sSA6 *sin6; 658 652 } ptr; 659 struct fd_list * li; 660 int ret; 661 662 sar.buf = NULL; 663 664 TRACE_ENTRY("%p %i %hu %p", sock, no_ip6, port, list); 665 CHECK_PARAMS( sock && list && (!FD_IS_LIST_EMPTY(list)) ); 666 667 if (no_ip6) { 668 family = AF_INET; 669 } else { 670 family = AF_INET6; 671 } 672 673 /* Create the socket */ 674 CHECK_SYS( *sock = socket(family, SOCK_STREAM, IPPROTO_SCTP) ); 675 676 /* Cleanup if we are cancelled */ 677 pthread_cleanup_push(fd_cleanup_socket, sock); 678 679 /* Set the socket options */ 680 CHECK_FCT_DO( ret = fd_setsockopt_prebind(*sock), goto fail ); 681 682 /* Create the array of addresses for sctp_connectx */ 653 683 654 for (li = list->next; li != list; li = li->next) { 684 655 struct fd_endpoint * ep = (struct fd_endpoint *) li; 685 656 686 count++; 687 688 /* Size of the new SA we are adding (sar may contain a mix of sockaddr_in and sockaddr_in6) */ 657 /* Do the flag match ? */ 658 if ((val & mask) != (ep->flags & mask)) 659 continue; 660 661 /* We add this endpoint at the end of array */ 662 (*count)++; 663 664 /* Size of the new SA we are adding (array may contain a mix of sockaddr_in and sockaddr_in6) */ 689 665 #ifndef SCTP_USE_MAPPED_ADDRESSES 690 666 if (ep->sa.sa_family == AF_INET6) … … 696 672 sz = sizeof(sSA4); 697 673 698 /* augment sarto contain the additional info */699 CHECK_MALLOC _DO( sar.buf = realloc(sar.buf, offset + sz), { ret = ENOMEM; goto fail; });700 701 ptr.buf = sar.buf +offset; /* place of the new SA */702 offset+= sz; /* update to end of sar */674 /* augment array to contain the additional info */ 675 CHECK_MALLOC( *array = realloc(*array, (*offset) + sz) ); 676 677 ptr.buf = *array + *offset; /* place of the new SA */ 678 (*offset) += sz; /* update to end of sar */ 703 679 704 680 if (sz == sizeof(sSA4)) { 705 681 memcpy(ptr.buf, &ep->sin, sz); 706 ptr.sin->sin_port = htons(port);682 ptr.sin->sin_port = port; 707 683 } else { 708 684 if (ep->sa.sa_family == AF_INET) { /* We must map the address */ … … 713 689 memcpy(ptr.sin6, &ep->sin6, sz); 714 690 } 715 ptr.sin6->sin6_port = htons(port); 716 } 717 } 691 ptr.sin6->sin6_port = port; 692 } 693 } 694 695 return 0; 696 } 697 698 /* Create a client socket and connect to remote server */ 699 int fd_sctp_client( int *sock, int no_ip6, uint16_t port, struct fd_list * list ) 700 { 701 int family; 702 int count = 0; 703 size_t offset = 0; 704 union { 705 uint8_t *buf; 706 sSA *sa; 707 } sar; 708 int ret; 709 710 sar.buf = NULL; 711 712 TRACE_ENTRY("%p %i %hu %p", sock, no_ip6, port, list); 713 CHECK_PARAMS( sock && list && (!FD_IS_LIST_EMPTY(list)) ); 714 715 if (no_ip6) { 716 family = AF_INET; 717 } else { 718 family = AF_INET6; 719 } 720 721 /* Create the socket */ 722 CHECK_SYS( *sock = socket(family, SOCK_STREAM, IPPROTO_SCTP) ); 723 724 /* Cleanup if we are cancelled */ 725 pthread_cleanup_push(fd_cleanup_socket, sock); 726 727 /* Set the socket options */ 728 CHECK_FCT_DO( ret = fd_setsockopt_prebind(*sock), goto fail ); 729 730 /* Create the array of addresses, add first the configured addresses, then the discovered, then the other ones */ 731 CHECK_FCT_DO( ret = add_addresses_from_list_mask(&sar.buf, &count, &offset, htons(port), list, EP_FL_CONF, EP_FL_CONF ), goto fail ); 732 CHECK_FCT_DO( ret = add_addresses_from_list_mask(&sar.buf, &count, &offset, htons(port), list, EP_FL_CONF | EP_FL_DISC, EP_FL_DISC ), goto fail ); 733 CHECK_FCT_DO( ret = add_addresses_from_list_mask(&sar.buf, &count, &offset, htons(port), list, EP_FL_CONF | EP_FL_DISC, 0 ), goto fail ); 718 734 719 735 /* Try connecting */ -
freeDiameter/tests/testcnx.c
r32 r38 471 471 struct connect_flags { 472 472 int proto; 473 int expect_failure; /* 0 or 1 */ 473 474 }; 474 475 … … 486 487 struct fd_endpoint * ep = (struct fd_endpoint *)(eps.next); 487 488 cnx = fd_cnx_cli_connect_tcp( &ep->sa, sSSlen(&ep->ss) ); 488 CHECK( 1, cnx ? 1 : 0);489 CHECK( 1, (cnx ? 1 : 0) ^ cf->expect_failure ); 489 490 } 490 491 break; … … 493 494 { 494 495 cnx = fd_cnx_cli_connect_sctp(0, TEST_PORT, &eps); 495 CHECK( 1, cnx ? 1 : 0);496 CHECK( 1, (cnx ? 1 : 0) ^ cf->expect_failure ); 496 497 } 497 498 break; … … 1510 1511 } 1511 1512 1513 /* Check that connection attempt fails then */ 1514 { 1515 struct connect_flags cf; 1516 1517 memset(&cf, 0, sizeof(cf)); 1518 cf.proto = IPPROTO_TCP; 1519 cf.expect_failure = 1; 1520 1521 /* Start the client thread, that should fail */ 1522 CHECK( 0, pthread_create(&thr, 0, connect_thr, &cf) ); 1523 CHECK( 0, pthread_join( thr, (void *)&client_side ) ); 1524 CHECK( 0, client_side ? 1 : 0 ); 1525 } 1526 1527 #ifndef DISABLE_SCTP 1528 { 1529 struct connect_flags cf; 1530 1531 memset(&cf, 0, sizeof(cf)); 1532 cf.proto = IPPROTO_SCTP; 1533 cf.expect_failure = 1; 1534 1535 /* Start the client thread, that should fail */ 1536 CHECK( 0, pthread_create(&thr, 0, connect_thr, &cf) ); 1537 CHECK( 0, pthread_join( thr, (void *)&client_side ) ); 1538 CHECK( 0, client_side ? 1 : 0 ); 1539 } 1540 #endif /* DISABLE_SCTP */ 1541 1542 1512 1543 /* That's all for the tests yet */ 1513 1544 PASSTEST(); -
include/freeDiameter/freeDiameter.h
r37 r38 540 540 int fd_ep_add_merge( struct fd_list * list, sSA * sa, socklen_t sl, uint32_t flags ); 541 541 int fd_ep_filter( struct fd_list * list, uint32_t flags ); 542 int fd_ep_filter_family( struct fd_list * list, int af ); 542 543 int fd_ep_clearflags( struct fd_list * list, uint32_t flags ); 543 544 void fd_ep_dump_one( char * prefix, struct fd_endpoint * ep, char * suffix );
Note: See TracChangeset
for help on using the changeset viewer.