📄 proxy.c
字号:
/*
*
* 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 + -