// contruct controlling context of UDP peers
CTRL_CTX *c_ctx = malloc(sizeof(CTRL_CTX));
c_ctx->in_serving = 0;
c_ctx->peerFirst = c_ctx->peerLast = NULL;
int ctrl_sockfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
int data_sockfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
char buffer[BUFFER_SIZE];
ssize_t recsize;
socklen_t udp_clilen;
struct sockaddr_in ctrl_saddr, data_saddr, udp_caddr;
udp_clilen = sizeof(udp_caddr);
// construct and bind the controlling socket
memset(&ctrl_saddr, 0, sizeof(ctrl_saddr));
ctrl_saddr.sin_family = AF_INET;
ctrl_saddr.sin_addr.s_addr = htonl(INADDR_ANY);
ctrl_saddr.sin_port = htons(7654);
if (bind(ctrl_sockfd,(struct sockaddr *) &ctrl_saddr, sizeof(ctrl_saddr)) == -1)
{
perror("error: udp bind failed");
close(ctrl_sockfd);
exit(EXIT_FAILURE);
}
// construct and bind the data tranmitting socket
memset(&data_saddr, 0, sizeof(data_saddr));
data_saddr.sin_family = AF_INET;
data_saddr.sin_addr.s_addr = htonl(INADDR_ANY);
data_saddr.sin_port = htons(7655);
if (bind(data_sockfd,(struct sockaddr *) &data_saddr, sizeof(data_saddr)) == -1)
{
perror("error: udp bind failed");
close(data_sockfd);
exit(EXIT_FAILURE);
}
/*
* initialize the file descriptor set
* to monitor the controlling socket use select()
*/
int rc;
struct pollfd ctrl_pfd;
ctrl_pfd.fd = ctrl_sockfd;
ctrl_pfd.events = POLLRDNORM;
int npfd = 1;
for (;;)
{
rc = poll(&ctrl_pfd, npfd, -1);
if (rc < 0)
{
perror("error: poll failed");
exit(EXIT_FAILURE);
}
if (ctrl_pfd.revents & POLLRDNORM)
{
printf("controlling socket is available to read.\n");
recsize = recvfrom(ctrl_sockfd, (void *)buffer, BUFFER_SIZE, 0, (struct sockaddr *) &udp_caddr, &udp_clilen);
if (recsize < 0)
{
fprintf(stderr, "%s\n", strerror(errno));
exit(EXIT_FAILURE);
}
else if (strncmp(buffer, "REQ", 3) == 0)
{
// a new client, record its information
register_new_peer();
}
else if (strncmp(buffer, "STP", 3) == 0)
{
// a client finished, ask to stop
de_register_a_peer();
}
else
printf("no information of of the client is found.\n");
}
/* the data socket is used to send packets for clients
* that have a record in the control context
*/
PEER_CTX *peer = c_ctx->peerFirst;
while (peer->peerNext != NULL)
{
// traverse the peers list, and send a packet
send_ncpkt(data_sockfd, (struct sockaddr *) &(peer->cli_addr), peer->cli_salen, s_ctx);
peer = peer->peerNext;
}
}