⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pmttrans.c

📁 DM500上用的着的动西懂着行的一定知道
💻 C
字号:
// pmttrans.c

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <pthread.h>
#include <signal.h>

#define PMT_SERVER_SOCKET "/tmp/.listen.camd.socket"
#define PMT_SERVER_SOCKET_BACKUP "/tmp/listen.camd.socket"

static int pmt_socket_backuped = 0;

static unsigned char pmt_buffer[1024];
static int pmt_len = 0;

static pthread_mutex_t pmt_distribute_lock;
static pthread_cond_t new_pmt_arrived;

static pthread_mutex_t connections_table_lock;
#define SIZE_OF_CONNECTIONS_TABLE	10
static int client_fd[SIZE_OF_CONNECTIONS_TABLE];

void utils_dump(char *label, unsigned char *data, int len)
{
	int i;
	printf(label);
	for(i = 0; i < len; i++) {
		printf("%02X ", data[i]);
        }
	printf(" [len=%02X]\n", len);
}

int is_pmt_valid(unsigned char *pmt, int pmt_size)
{
	if (pmt_size < 31)
		return 0;
	if (memcmp(pmt, "\x9f\x80\x32\x82", 4) == 0)
		return 1;
	return 0;
}

struct PMT_ENTRY
{
	unsigned char stream_type;
	unsigned char pid[2];
	unsigned char ca_descriptor_len[2];
	unsigned char *ca_descriptor;
};

int convert_pmt(unsigned char *original_pmt, int pmt_size, unsigned char *new_pmt)
{
	if (is_pmt_valid(original_pmt, pmt_size) == 0)
	{
		memcpy(new_pmt, original_pmt, pmt_size);
		return pmt_size;
	}

	struct PMT_ENTRY pmt_entry[10];
	int pmt_entry_count = 0;

	int len = (original_pmt[10] << 8) + original_pmt[11];
	int base_info_len = 12 + len;
	int wp = base_info_len;

	while (wp < pmt_size)
	{
		memcpy(&(pmt_entry[pmt_entry_count]), original_pmt + wp, 5);
		len = (pmt_entry[pmt_entry_count].ca_descriptor_len[0] << 8) + pmt_entry[pmt_entry_count].ca_descriptor_len[1];
		wp += 5;
		if (len == 0)
			pmt_entry[pmt_entry_count].ca_descriptor = NULL;
		else
		{
			pmt_entry[pmt_entry_count].ca_descriptor = original_pmt + wp;
			wp += len;
		}
		pmt_entry_count++;
	}

	int i = 0;
	int bp = 0, np = 0;
	while (i < pmt_entry_count)
	{
		memcpy(new_pmt + bp, original_pmt, base_info_len);
		np = base_info_len;

		do
		{
			memcpy(new_pmt + bp + np, &(pmt_entry[i]), 5);
			np += 5;
			len = (pmt_entry[i].ca_descriptor_len[0] << 8) + pmt_entry[i].ca_descriptor_len[1];
			if (len > 0)
			{
				memcpy(new_pmt + bp + np, pmt_entry[i].ca_descriptor, len);
				np += len;
			}

			if (i == pmt_entry_count - 1)
				break;

			if (pmt_entry[i + 1].ca_descriptor == NULL)
				i++;
			else
			{
				if (pmt_entry[i].ca_descriptor == NULL)
					break;
				else
				{
					if (len == ((pmt_entry[i + 1].ca_descriptor_len[0] << 8) + pmt_entry[i + 1].ca_descriptor_len[1]) &&
						memcmp(pmt_entry[i].ca_descriptor, pmt_entry[i + 1].ca_descriptor, len) == 0)
						i++;
					else
						break;
				}
			}
		} while (1);

		len = np - 6;
		new_pmt[bp + 4] = (len >> 8) & 0xFF;
		new_pmt[bp + 5] = len & 0xFF;
		i++;
		if (bp == 0)
		{
			if (i == pmt_entry_count)
				new_pmt[bp + 6] = 3;
			else
				new_pmt[bp + 6] = 1;
		}
		else
		{
			if (i == pmt_entry_count)
				new_pmt[bp + 6] = 2;
			else
				new_pmt[bp + 6] = 0;
		}
		bp += np;
	}

	return bp;
}

void add_to_connections_table(int clientfd)
{
	int i;
	pthread_mutex_lock(&connections_table_lock);
	for (i = 0; i < SIZE_OF_CONNECTIONS_TABLE; i++)
	{
		if (client_fd[i] == -1)
		{
			client_fd[i] = clientfd;
			break;
		}
	}
	pthread_mutex_unlock(&connections_table_lock);
}

void *new_pmt_server_proc(void *pdata)
{
	int newpmtfd;
	struct sockaddr_un saddr;

	printf("Trying start new PMT listen socket...\n");

	/* socket init */
	saddr.sun_family = AF_UNIX;
	strncpy(saddr.sun_path, PMT_SERVER_SOCKET, 107);
	saddr.sun_path[107] = '\0';
	unlink(saddr.sun_path);
	if((newpmtfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
		printf("socket error (errno=%d)\n", errno);
		perror("");
		exit(1);
	}
	if (bind(newpmtfd, (struct sockaddr *)&saddr,
		sizeof(saddr.sun_family)+strlen(saddr.sun_path) ) < 0) {
		printf("socket bind error (errno=%d)\n", errno);
		perror("");
		exit(2);
	}
	if (listen(newpmtfd, 5) < 0) {
		printf("socket listen error (errno=%d)\n", errno);
		perror("");
		exit(3);
	}

	pthread_mutex_init(&connections_table_lock, NULL);

	while(1)
	{
		struct sockaddr_in client_addr;
		socklen_t length = sizeof(client_addr);

		int clientfd = accept(newpmtfd,(struct sockaddr*)&client_addr,&length);
		if (clientfd < 0)
		{
			printf("PMT server accept error (errno=%d)\n", errno);
			perror("");
			break;
		}

		pthread_mutex_lock(&pmt_distribute_lock);
		if (send(clientfd, pmt_buffer, pmt_len, 0) == pmt_len)
		{
			add_to_connections_table(clientfd);
			printf("A client connected.\n");
		}
		pthread_mutex_unlock(&pmt_distribute_lock);
	}

	pthread_exit(NULL);
}

void *pmt_distribute_proc(void *pdata)
{
	int i, len;

	pthread_mutex_lock(&pmt_distribute_lock);

	while(pthread_cond_wait(&new_pmt_arrived, &pmt_distribute_lock) == 0)
	{
		pthread_mutex_lock(&connections_table_lock);
		for (i = 0; i < SIZE_OF_CONNECTIONS_TABLE; i++)
		{
			if (client_fd[i] != -1)
			{
				printf("sending, client fd is %d\n", client_fd[i]);
				len = send(client_fd[i], pmt_buffer, pmt_len, MSG_NOSIGNAL);
				printf("sended, return value is %d\n", len);
				if (len != pmt_len)
				{
					printf("send error, client fd is %d, return value is %d, errno=%d\n", client_fd[i], len, errno);
					perror("");
					close(client_fd[i]);
					client_fd[i] = -1;
				}
			}
		}
		pthread_mutex_unlock(&connections_table_lock);
	}

	pthread_mutex_unlock(&pmt_distribute_lock);

	pthread_exit(NULL);
}

void init_daemon(void)
{
	int pid;
	int fd, fdtablesize;

	/* 蹇界暐缁堢

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -