/*
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>#define UDP_BUFF_SZ (2 << 8) /* 256b */
#define PACKET_SIZE (2 << 5) /* 32Kb */
/* Global pipe */
int pipefd[2] = {EOF, EOF};
/* for setsockopt */
const unsigned long value = PACKET_SIZE;
/* считать ровно 32 кб из pipefd[0] , в буфер */
void *read_thread(void *p __attribute__((unused)))
{
int sz;
unsigned int data = PACKET_SIZE;
char *tmp = (char *)malloc(PACKET_SIZE);
while (data) {
if ((sz = read(pipefd[0], tmp, data)) == -1) {
close(pipefd[0]);
free(tmp);
pthread_exit((void *) EOF);
}
data -= sz;
tmp += sz;
}
free(tmp);
return(NULL);
}
void *udp_thread(void *a __attribute__((unused)))
{
socklen_t saddrlen;
socklen_t val_len = sizeof(value);
int fd;
struct sockaddr_in serv_addr;
char udp_buff[UDP_BUFF_SZ];
fd = socket(AF_INET, (int) SOCK_DGRAM, IPPROTO_UDP);
if (fd < 0) {
pthread_exit(NULL);
}
memset((void *)&serv_addr, 0, sizeof(struct sockaddr_in));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(10000);
serv_addr.sin_addr.s_addr = INADDR_ANY;
if (bind(fd, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr_in)) < 0) {
close(fd);
pthread_exit(NULL);
}
while (1) {
saddrlen = sizeof(serv_addr);
if (recvfrom(fd, udp_buff, UDP_BUFF_SZ - 1, 0,
(struct sockaddr *)&serv_addr,
(socklen_t *)&saddrlen) < 0)
{
continue;
}
fcntl(fd, F_SETFL, ~O_NONBLOCK);
if (dup2(fd, pipefd[1]) < 0) {
pthread_exit((void *) EOF);
} else {
setsockopt(pipefd[1], SOL_SOCKET, SO_RCVBUF, &value, val_len);
}
}
return(NULL);
}
int main(void)
{
pthread_t pth[2];
pthread_attr_t pattr;
pipe2(pipefd, O_NONBLOCK);
(void) pthread_attr_init(&pattr);
(void) pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_DETACHED);
if ((pthread_create(&pth[0], &pattr, udp_thread, NULL)) != 0) {
return(errno);
}
if ((pthread_create(&pth[1], &pattr, read_thread, NULL)) != 0) {
return(errno);
}
MainStateChecker(); /* независимая хрень */
return(EXIT_SUCCESS);
}