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

📄 proxy.c

📁 RTSP Proxy in C language
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 
  * 
  *  kRtspProxyd
  * 
  *  Many basic functions for rtsp parsing
  *
  */

#include <linux/kernel.h>
#include <linux/net.h>
#include <net/sock.h>
#include <linux/inet.h>
#include "proxy.h"
#include "prototypes.h"

#define MAX_SOCK_ADDR 128
int	gUserLimit = 20;
atomic_t	gNumUsers = ATOMIC_INIT(0);
shok	*gShokList = NULL;

static int gUDPPortMin = 2000;
static int gUDPPortMax = 65536;
atomic_t gNextPort = ATOMIC_INIT(-1);
atomic_t gMaxPorts = ATOMIC_INIT(0);
unsigned int gProxyIP; //sefIP


t_cmd_map cmd_map[] = {
	{"DESCRIBE",	ttDescribe},
	{"SETUP",	ttSetup},	
	{"PLAY",	ttPlay},
	{"PAUSE",	ttPause},
	{"STOP",	ttStop},
	{"TEARDOWN",	ttTeardown},
	{"OPTIONS",     ttOptions},
	{"ANNOUNCE",    ttAnnounce},
	{"REDIRECT", 	ttRedirect},
	{"GET_PARAMETER", ttGetParameter},
	{"SET_PARAMETER", ttSetParameter},
	{NULL,		ttNone}
};

char *str_sep(char **stringp, char *delim)
{
	int j, dl, i, sl;
	char *newstring, *ret;

	if (*stringp == NULL)
		return NULL;

	dl = strlen(delim);
	sl = strlen(*stringp);
	newstring = NULL;
	ret = *stringp;

	for (i=0; i<sl; i++) {
		for (j=0; j<dl; j++) {
			if ((*stringp)[i] == delim[j]) {
				(*stringp)[i] = '\0';
				newstring = &((*stringp)[i+1]);
				i = sl; j = dl;
			}
		}
	}

	*stringp = newstring;
	return ret;
}


static inline char to_lower(char c)
{
	if (c >= 'A' && c <= 'Z')
		return ((c - 'A') + 'a');
	return c;
}


int strn_casecmp(char *str1, char *str2, int l)
{
	int	ret;
	
	ret = to_lower(*str1) - to_lower(*str2);
	while (l-- && to_lower(*str1) && to_lower(*str2) && ((ret = to_lower(*str1++) - to_lower(*str2++)) == 0))
		;
	return ret;
}

int is_command(char *inp, char *cmd, char *server)
{
	int 	l;
	char	*p;

	l = strlen(inp);

	if (l < 17)		/* "RTSP/1.0" (8) + " rtsp:// " (9) */
		return 0;
	if (strn_casecmp(&inp[l-8], "RTSP/1.0", 8) != 0)
		return 0;

	p = inp;
	while (*p && (*p != ' '))
		*cmd++ = *p++;
	*cmd = '\0';

	if (strn_casecmp(p, " rtsp://", 8) != 0)
		return 0;

	p += 8;
	while (*p && (*p != '/'))
		*server++ = *p++;
	*server = '\0';

	return 1;
}

/**********************************************/
int has_two_crlfs(char *s)
{
	int		l, n;
	char	*p;
	l = strlen(s);
	if (l < 4)
		return 0;
	n = 3;
	p = s + n;
	while (n < l) {
		if (s[n] != '\n')
			n += 1;
		else if (s[n-1] != '\r' || s[n-2] != '\n' || s[n-3] != '\r')
			n += 2;
		else
			return n+1;
	}
	return 0;
}


void send_rtsp_error(struct socket *sock, int refusal)
{ 

       char *refusal_string;

       EnterFunction("send_rtsp_error");
       
	switch (refusal) {
		case kServerNotFound:
 			refusal_string = "RTSP/1.0 462 Destination unreachable\r\n";
			break;
		case kUnknownError:
 			refusal_string = "RTSP/1.0 500 Unknown proxy error\r\n";
			break;
		case kPermissionDenied:
 			refusal_string = "RTSP/1.0 403 Proxy denied\r\n";
			break;
		case kTooManyUsers:
 			refusal_string = "RTSP/1.0 503 Too many proxy users\r\n";
			break;
		default:
 			refusal_string = "RTSP/1.0 500 Unknown proxy error\r\n";
			break;
	}

	(void)SendBuffer(sock, refusal_string, strlen(refusal_string));
	LeaveFunction("send_rtsp_error");
}

int str_casecmp(char *str1, char *str2)
{
	int	ret;
	
	ret = *str1 - *str2;
	while (*str1 && *str2 && ((ret = *str1++ - *str2++) == 0))
		;
	return ret;
}

int cmd_to_transaction_type(char *cmd)
{
	t_cmd_map	*map;
	map = cmd_map;
	while (map->cmd != NULL) {
		if (str_casecmp(map->cmd, cmd) == 0)
			return map->type;
		map++;
	}
	return ttNone;
}

/**********************************************/
int has_trackID(char *inp, int *trackID)
{
	int 	l;
	char	*p;
	l = strlen(inp);

	if (l < 18)		/* "RTSP/1.0" (8) + "trackID=n " (10) */
		return 0;
	if (strn_casecmp(inp + l - 8, "RTSP/1.0", 8) != 0)
		return 0;

	p = inp;
	while (p) {
		p = strchr(p, '=');
		if (p - 7 < inp) {
			p++;
			continue;
		}
		if (strn_casecmp(p - 7, "trackid=", 8) != 0) {
			p++;
			continue;
		}
		*trackID = atoi(p + 1);
		return 1;
	}
	return 0;
}


int track_id_to_idx(rtsp_session *s, int id)
{
	int i;
	for (i=0; i<s->numTracks; i++) {
		if (s->trk[i].ID == id)
			return i;
	}
	return -1;
}

/**********************************************/
int has_client_port(char *inp, unsigned short *port)
{
	int		l;
	char	*p;
	l = strlen(inp);

	if (l < 23)		/* "Transport:<>client_port=n" (23) */
		return 0;
	if (strn_casecmp(inp, "transport", 9) != 0)
		return 0;
	
	p = inp;
	while (p) {
		p = strchr(p, '=');
		if (p - 11 < inp) {
			p++;
			continue;
		}
		if (strn_casecmp(p - 11, "client_port=", 12) != 0) {
			p++;
			continue;
		}
		*port = atoi(p + 1);
		*++p = '\0';
		return 1;
	}
	return 0;
}


ipList *find_ip_in_list(ipList *list, unsigned int ip)
{
	ipList *cur = list;

      EnterFunction("find_ip_in_list");

	while (cur) {
	
		if (cur->ip == ip) {
			return cur;
		}
		cur = cur->next;
	}
      LeaveFunction("find_ip_in_list");
      return NULL;
}

shok *find_available_shok(unsigned int fromIP, unsigned int toIP, int withSib, const int CPUNR)
{	
	shok	*cur = threadinfo[CPUNR].gShokQueue;

	while (cur) {
		KRTSPROXYD_OUT(KERN_INFO " looking for IP %xin shok\n", toIP);
		if (find_ip_in_list(cur->ips, toIP) == NULL) {
			if (withSib) {
				KRTSPROXYD_OUT(KERN_INFO "looking for IP %x in SIB shok\n", toIP);
				if (find_ip_in_list(cur->sib->ips, toIP) == NULL)
					return cur;
			}
			else
				return cur;
		}
		cur = cur->next;
	}

	return NULL;
}

int add_ip_to_list(ipList **list, unsigned int ip)
{
	ipList	*newEl;

	newEl = (ipList*)kmalloc(sizeof(ipList), GFP_KERNEL);
	if (!newEl)
		return 0;
	newEl->ip = ip;
	newEl->what_to_do = NULL;
	newEl->what_to_do_it_with = NULL;
	newEl->next = *list;
	*list = newEl;

	return 1;
}

 struct socket *new_socket_tcp(void)
{
	struct socket *sock;
	int err;
	
       err = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
      	
	if (err<0) 
       {
	     KRTSPROXYD_OUT(KERN_ERR "Error during creation of tcp socket; terminating\n");
	     sock_release(sock);
	     return NULL;
	}    
	atomic_inc(&gMaxPorts);
	return sock;
}

void set_socket_reuse_address(struct socket *skt)
{
	int i = 1;
	skt->sk->prot->setsockopt(skt->sk, SOL_SOCKET, SO_REUSEADDR, (char*)&i, sizeof(i));
}

/**********************************************/
static struct socket *new_socket_udp(void)
{
	struct socket *sock = NULL;
	int err;
	
       err = sock_create(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);
	if (err<0) 
       {
	     KRTSPROXYD_OUT(KERN_ERR "Error during creation of udp socket; terminating\n");
	     sock_release(sock);
	     return NULL;
	}    
	atomic_inc(&gMaxPorts);
	return sock;
}

int bind_socket_to_address(struct socket *skt, unsigned int address, unsigned short port, int is_listener)
{
	struct sockaddr_in sin;
	int err;

	if (address == (unsigned int)0xFFFFFFF)
		address = INADDR_ANY;
		
	memset(&sin, 0, sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_port = htons(port);
	sin.sin_addr.s_addr = address; //already is network byte order!

	err = skt->ops->bind(skt,(struct sockaddr*)&sin,sizeof(sin));
	if (err < 0)
	{
		KRTSPROXYD_OUT(KERN_ERR "kRtspProxyd: Error binding socket. This means that some other \n");
		KRTSPROXYD_OUT(KERN_ERR "        daemon is (or was a short time ago) using port %i.\n",port);
		return 0;	
	}

	/* Grrr... setsockopt() does this. */
//	skt->sk->reuse   = 1; //success!!
       return 1;
}

//fromIp and toIp are all NBO
shok *make_new_shok(unsigned int fromIP, unsigned int toIP, int withSib, const int CPUNR)
{
	shok *theShok1 = NULL, *theShok2 = NULL;
	struct socket *skt1 = NULL, *skt2 = NULL;
	unsigned short port1 = (unsigned short)0xFFFF, port2 = (unsigned short)0xFFFF;

	theShok1 = (shok*)kmalloc(sizeof(shok), GFP_KERNEL);
	if (!theShok1)
		goto bail_error;
	if (withSib) {
		theShok2 = (shok*)kmalloc(sizeof(shok), GFP_KERNEL);
		if (!theShok2)
			goto bail_error;
	}

	if (atomic_read(&gNextPort) == -1)
		atomic_set(&gNextPort, gUDPPortMin);

retry:

	if ((skt1 = new_socket_udp()) == NULL)
		goto bail_error;

       	if ((atomic_read(&gNextPort) & 0x1) && withSib) //odd number
			atomic_inc(&gNextPort);
		if (atomic_read(&gNextPort) > gUDPPortMax)
          		atomic_set(&gNextPort, gUDPPortMin);
 while (bind_socket_to_address(skt1, fromIP, port1 = atomic_read(&gNextPort), 0) != 1)
 	{
 	    atomic_inc(&gNextPort);
 	    if ((atomic_read(&gNextPort) & 0x1) && withSib) //odd number
			atomic_inc(&gNextPort);
		if (atomic_read(&gNextPort) > gUDPPortMax)
          		atomic_set(&gNextPort, gUDPPortMin);
 	}
 atomic_inc(&gNextPort);

 if (withSib) {
       	if ((skt2 = new_socket_udp()) == NULL)
			goto bail_error;

		if (bind_socket_to_address(skt2, fromIP, port2 = atomic_read(&gNextPort), 0) != 1) {
			sock_release(skt1);
			sock_release(skt2);
			skt1 = NULL;
			skt2 = NULL;
			atomic_inc(&gNextPort);
			goto retry;
		}
		else atomic_inc(&gNextPort);
	}

       make_socket_nonblocking(skt1);
	theShok1->socket = skt1;
	theShok1->port = port1;
	theShok1->ips = NULL;

	if (withSib) {
              make_socket_nonblocking(skt2);

		theShok2->socket = skt2;
		theShok2->port = port2;
		theShok2->ips = NULL;
		theShok2->sib = theShok1;

		theShok1->sib = theShok2;
		theShok1->next = theShok2;
		theShok2->next = threadinfo[CPUNR].gShokQueue;
	}
	else {
		theShok1->sib = NULL;
		theShok1->next = threadinfo[CPUNR].gShokQueue;
	}

	add_ips_to_shok(theShok1, fromIP, toIP, withSib);
	threadinfo[CPUNR].gShokQueue = theShok1;

	return theShok1;	

bail_error:
	sock_release(skt1);
	sock_release(skt2);
	if (theShok1 != NULL)
		kfree(theShok1);
	if (theShok2 != NULL)
		kfree(theShok2);
	return NULL;

⌨️ 快捷键说明

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