723 lines
20 KiB
C
723 lines
20 KiB
C
/*
|
|
* Copyright (C) 2004 Nathan Lutchansky <lutchann@litech.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "lwip\sockets.h"
|
|
#include "lwip\netif.h"
|
|
#include "lwip\dns.h"
|
|
// #include "lwip\fcntl.h"
|
|
#include "lwip\api.h"
|
|
|
|
#include "typesdef.h"
|
|
// #include <linux/linux_mutex.h>
|
|
#include <event.h>
|
|
#include <log.h>
|
|
#include <frame.h>
|
|
#include <stream.h>
|
|
#include <pmsg.h>
|
|
#include <rtp.h>
|
|
#include "lwip/api.h"
|
|
// #include "leases.h"
|
|
// #include "dhcpd.h"
|
|
|
|
static int base64[] = {
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 00 */
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10 */
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /* 20 */
|
|
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, 0, -1, -1, /* 30 */
|
|
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 40 */
|
|
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /* 50 */
|
|
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 60 */
|
|
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, /* 70 */
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80 */
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 90 */
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* A0 */
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* B0 */
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* C0 */
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* D0 */
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* E0 */
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* F0 */
|
|
};
|
|
|
|
void write_access_log(char *path, struct sockaddr *addr, int code, char *req, int length, char *referer, char *user_agent);
|
|
|
|
struct listener
|
|
{
|
|
int fd;
|
|
};
|
|
|
|
/* all of tcp connetctions loop linked list */
|
|
static struct conn *conn_list = NULL;
|
|
|
|
static void do_read(void *ei, void *d);
|
|
|
|
void drop_conn(struct conn *c)
|
|
{
|
|
if (c->read_event)
|
|
{
|
|
eloop_remove_event(c->read_event);
|
|
c->read_event = NULL;
|
|
}
|
|
|
|
if (c->write_event)
|
|
{
|
|
eloop_remove_event(c->write_event);
|
|
c->write_event = NULL;
|
|
}
|
|
if (c->fd >= 0)
|
|
{
|
|
close(c->fd);
|
|
}
|
|
c->fd = -1;
|
|
os_event_del(&c->evt);
|
|
if (c->next)
|
|
{
|
|
c->next->prev = c->prev;
|
|
}
|
|
if (c->prev)
|
|
{
|
|
c->prev->next = c->next;
|
|
}
|
|
else
|
|
{
|
|
conn_list = c->next;
|
|
}
|
|
|
|
if (c->proto_state)
|
|
{
|
|
free(c->proto_state);
|
|
c->proto_state = NULL;
|
|
}
|
|
free(c);
|
|
_os_printf("%s finish\n", __FUNCTION__);
|
|
}
|
|
|
|
static void conn_write(void *ei, void *d)
|
|
{
|
|
spook_log(SL_DEBUG, "tcp_w");
|
|
struct conn *c = (struct conn *) d;
|
|
int ret, len;
|
|
struct session *sess;
|
|
|
|
while (c->send_buf_r != c->send_buf_w)
|
|
{
|
|
if (c->send_buf_w < c->send_buf_r)
|
|
{
|
|
len = sizeof(c->send_buf) - c->send_buf_r;
|
|
}
|
|
else
|
|
{
|
|
len = c->send_buf_w - c->send_buf_r;
|
|
}
|
|
|
|
// 等待1ms,没有完成就退出,等待下一次
|
|
int evt_err = os_event_wait(&c->evt, RTSP_TCP_READ_MUTEX|RTSP_TCP_WRITE_MUTEX, NULL, OS_EVENT_WMODE_AND | OS_EVENT_WMODE_CLEAR, 1);
|
|
if (!evt_err)
|
|
{
|
|
ret = write(c->fd, c->send_buf + c->send_buf_r, len);
|
|
os_event_set(&c->evt, RTSP_TCP_READ_MUTEX | RTSP_TCP_WRITE_MUTEX, NULL);
|
|
}
|
|
//没有成功,则直接退出,下次重新尝试发送
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (ret <= 0)
|
|
{
|
|
if (ret < 0 && get_errno() == EAGAIN)
|
|
{
|
|
return;
|
|
}
|
|
// drop_conn( c );
|
|
|
|
goto conn_write_exit;
|
|
}
|
|
c->send_buf_r += ret;
|
|
if (c->send_buf_r == sizeof(c->send_buf))
|
|
{
|
|
c->send_buf_r = 0;
|
|
}
|
|
}
|
|
|
|
if (c->drop_after)
|
|
{
|
|
goto conn_write_exit;
|
|
}
|
|
else
|
|
{
|
|
eloop_set_event_enabled(c->write_event, 0);
|
|
}
|
|
|
|
// 缓冲buf已经发送完成,所以将读和写重置(这种设置方式,不能存在异步,所以只能全部在event_loop,event_loop相当于单线程)
|
|
c->send_buf_r = 0;
|
|
c->send_buf_w = 0;
|
|
return;
|
|
conn_write_exit:
|
|
sess = c->sess;
|
|
_os_printf("close sess:%x\r\n", (int) sess);
|
|
if (sess)
|
|
{
|
|
// sess->conn = NULL;
|
|
_os_printf("close sess->close:%x\r\n", (int) sess->closed);
|
|
sess->closed(sess, NULL);
|
|
}
|
|
|
|
// 关闭自己的事件和socket
|
|
if (c->read_event)
|
|
{
|
|
eloop_remove_event(c->read_event);
|
|
c->read_event = NULL;
|
|
}
|
|
if (c->write_event)
|
|
{
|
|
eloop_remove_event(c->write_event);
|
|
c->write_event = NULL;
|
|
}
|
|
|
|
if (c->fd >= 0)
|
|
{
|
|
close(c->fd);
|
|
c->fd = -1;
|
|
}
|
|
return;
|
|
}
|
|
|
|
int avail_send_buf(struct conn *c)
|
|
{
|
|
if (c->send_buf_r > c->send_buf_w)
|
|
{
|
|
return c->send_buf_r - c->send_buf_w - 1;
|
|
}
|
|
else
|
|
{
|
|
return sizeof(c->send_buf) - c->send_buf_w + c->send_buf_r - 1;
|
|
}
|
|
}
|
|
|
|
int send_data(struct conn *c, unsigned char *d, int len)
|
|
{
|
|
if (avail_send_buf(c) < len)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
while (--len >= 0)
|
|
{
|
|
c->send_buf[c->send_buf_w++] = *(d++);
|
|
if (c->send_buf_w == sizeof(c->send_buf))
|
|
{
|
|
c->send_buf_w = 0;
|
|
}
|
|
}
|
|
|
|
eloop_set_event_enabled(c->write_event, EVENT_F_ENABLED);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int tcp_send_pmsg(struct conn *c, struct pmsg *msg, int len)
|
|
{
|
|
char buf[512];
|
|
int i, f, totlen;
|
|
|
|
if (msg->type != PMSG_RESP)
|
|
{
|
|
return -1;
|
|
}
|
|
i = sprintf(buf, "%s %d %s\r\n", msg->proto_id, msg->sl.stat.code, msg->sl.stat.reason);
|
|
for (f = 0; f < msg->header_count; ++f)
|
|
{
|
|
i += sprintf(buf + i, "%s: %s\r\n", msg->fields[f].name, msg->fields[f].value);
|
|
}
|
|
if (len >= 0)
|
|
{
|
|
i += sprintf(buf + i, "Content-Length: %d\r\n\r\n", len);
|
|
totlen = i + len;
|
|
}
|
|
else
|
|
{
|
|
i += sprintf(buf + i, "\r\n");
|
|
totlen = i;
|
|
}
|
|
if (avail_send_buf(c) < totlen)
|
|
{
|
|
return -1;
|
|
}
|
|
_os_printf("%s\r\n", buf);
|
|
send_data(c, (unsigned char *) buf, i);
|
|
return 0;
|
|
}
|
|
|
|
static void log_request(struct req *req, int code, int length)
|
|
{
|
|
char *ref, *ua;
|
|
|
|
ref = get_header(req->req, "referer");
|
|
ua = get_header(req->req, "user-agent");
|
|
write_access_log(NULL, (struct sockaddr *) &req->conn->client_addr, code, (char *) req->conn->req_buf, length, ref ? ref : "-", ua ? ua : "-");
|
|
}
|
|
|
|
static int handle_unknown(struct req *req)
|
|
{
|
|
log_request(req, 501, 0);
|
|
req->conn->drop_after = 1;
|
|
req->resp = new_pmsg(256);
|
|
req->resp->type = PMSG_RESP;
|
|
req->resp->proto_id = add_pmsg_string(req->resp, req->req->proto_id);
|
|
req->resp->sl.stat.code = 501;
|
|
req->resp->sl.stat.reason = add_pmsg_string(req->resp, "Not Implemented");
|
|
copy_headers(req->resp, req->req, "CSeq");
|
|
tcp_send_pmsg(req->conn, req->resp, -1);
|
|
return 0;
|
|
}
|
|
|
|
static int handle_request(struct conn *c)
|
|
{
|
|
int ret;
|
|
struct req *req;
|
|
|
|
if (c->req_buf[0] == 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
if ((req = malloc(sizeof(struct req))) == NULL)
|
|
{
|
|
return -1;
|
|
}
|
|
req->conn = c;
|
|
req->resp = NULL;
|
|
req->req = new_pmsg(c->req_len);
|
|
req->req->msg_len = c->req_len;
|
|
memcpy(req->req->msg, c->req_buf, req->req->msg_len);
|
|
if (parse_pmsg(req->req) < 0)
|
|
{
|
|
free_pmsg(req->req);
|
|
free(req);
|
|
return -1;
|
|
}
|
|
spook_log(SL_VERBOSE, "client request: '%s' '%s' '%s'", req->req->sl.req.method, req->req->sl.req.uri, req->req->proto_id);
|
|
|
|
switch (c->proto)
|
|
{
|
|
case CONN_PROTO_RTSP:
|
|
ret = rtsp_handle_msg(req);
|
|
break;
|
|
default:
|
|
ret = handle_unknown(req);
|
|
break;
|
|
}
|
|
if (ret <= 0)
|
|
{
|
|
free_pmsg(req->req);
|
|
if (req->resp)
|
|
{
|
|
free_pmsg(req->resp);
|
|
}
|
|
free(req);
|
|
}
|
|
return ret < 0 ? -1 : 0;
|
|
}
|
|
|
|
static int parse_client_data(struct conn *c)
|
|
{
|
|
char *a, *b;
|
|
|
|
switch (c->proto)
|
|
{
|
|
case CONN_PROTO_START:
|
|
if ((a = strchr((const char *) c->req_buf, '\n')))
|
|
{
|
|
*a = 0;
|
|
if (!(b = strrchr((const char *) c->req_buf, ' ')))
|
|
{
|
|
return -1;
|
|
}
|
|
if (!strncmp(b + 1, "HTTP/", 5))
|
|
{
|
|
c->proto = CONN_PROTO_HTTP;
|
|
}
|
|
else if (!strncmp(b + 1, "RTSP/", 5))
|
|
{
|
|
c->proto = CONN_PROTO_RTSP;
|
|
}
|
|
else if (!strncmp(b + 1, "APPO/", 5))
|
|
{
|
|
c->proto = CONN_PROTO_APPO;
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
*a = '\n';
|
|
return 1;
|
|
}
|
|
break;
|
|
case CONN_PROTO_RTSP:
|
|
if (c->req_len < 4)
|
|
{
|
|
return 0;
|
|
}
|
|
if (c->req_buf[0] == '$')
|
|
{
|
|
spook_log(SL_DEBUG, "interleave_recv\n");
|
|
if (c->req_len < GET_16(c->req_buf + 2) + 4)
|
|
{
|
|
return 0;
|
|
}
|
|
#if 0
|
|
interleave_recv( c, c->req_buf[1], c->req_buf + 4,
|
|
GET_16( c->req_buf + 2 ) );
|
|
#else
|
|
c->req_len -= (GET_16(c->req_buf + 2) + 4);
|
|
|
|
#endif
|
|
/* should really just delete the packet from the
|
|
* buffer, not the entire buffer */
|
|
// c->req_len = 0;
|
|
}
|
|
else
|
|
{
|
|
if (!strstr((const char *) c->req_buf, (const char *) "\r\n\r\n"))
|
|
{
|
|
return 0;
|
|
}
|
|
if (handle_request(c) < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
/* should really just delete the request from the
|
|
* buffer, not the entire buffer */
|
|
c->req_len = 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int unbase64(unsigned char *d, int len, int *remain)
|
|
{
|
|
int src = 0, dest = 0, i;
|
|
unsigned char enc[4];
|
|
|
|
for (;;)
|
|
{
|
|
for (i = 0; i < 4; ++src)
|
|
{
|
|
if (src >= len)
|
|
{
|
|
if (i > 0)
|
|
{
|
|
memcpy(d + dest, enc, i);
|
|
}
|
|
*remain = i;
|
|
return dest + i;
|
|
}
|
|
if (base64[d[src]] < 0)
|
|
{
|
|
continue;
|
|
}
|
|
enc[i++] = d[src];
|
|
}
|
|
d[dest] = ((base64[enc[0]] << 2) & 0xFC) | (base64[enc[1]] >> 4);
|
|
d[dest + 1] = ((base64[enc[1]] << 4) & 0xF0) | (base64[enc[2]] >> 2);
|
|
d[dest + 2] = ((base64[enc[2]] << 6) & 0xC0) | base64[enc[3]];
|
|
if (enc[3] == '=')
|
|
{
|
|
if (enc[2] == '=')
|
|
{
|
|
dest += 1;
|
|
}
|
|
else
|
|
{
|
|
dest += 2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dest += 3;
|
|
}
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
static unsigned char s_ptemp[300] = {"TEARDOWN rtsp://192.168.1.1:7070/webcam/ RTSP/1.0\r\nCSeq: 6\r\nUser-Agent: Lavf56.40.101\r\nSession: 9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9\r\n\r\n4A5A6A7A8A9\r\n\r\n"};
|
|
#endif
|
|
|
|
static void do_read(void *ei, void *d)
|
|
{
|
|
_os_printf("%s:%d\n", __FUNCTION__, __LINE__);
|
|
spook_log(SL_DEBUG, "tcp do_read");
|
|
struct conn *c = (struct conn *) d;
|
|
int ret;
|
|
struct session *sess = NULL;
|
|
|
|
for (;;)
|
|
{
|
|
os_event_wait(&c->evt, RTSP_TCP_READ_MUTEX, NULL, OS_EVENT_WMODE_AND | OS_EVENT_WMODE_CLEAR, -1);
|
|
ret = read(c->fd, c->req_buf + c->req_len, sizeof(c->req_buf) - c->req_len - 1);
|
|
os_event_set(&c->evt, RTSP_TCP_READ_MUTEX, NULL);
|
|
|
|
if (ret <= 0)
|
|
{
|
|
if (ret < 0)
|
|
{
|
|
if (get_errno() == EAGAIN)
|
|
{
|
|
spook_log(SL_VERBOSE, "get_errno() === %x", get_errno());
|
|
return;
|
|
}
|
|
spook_log(SL_VERBOSE, "get_errno() = %x", get_errno());
|
|
spook_log(SL_VERBOSE, "closing TCP connection to client due to read error: %s ret:%d", strerror(get_errno()), ret);
|
|
}
|
|
else
|
|
{
|
|
spook_log(SL_VERBOSE, "client closed TCP connection %x c:%X", c->sess, c);
|
|
/* add by jornny */
|
|
/* should be initialized by NULL */
|
|
}
|
|
|
|
spook_log(SL_DEBUG, "free conn");
|
|
// drop_conn( c );
|
|
|
|
/* add by jornny */
|
|
/* drop_conn has free c, so can not use c->sess !!!*/
|
|
sess = c->sess;
|
|
|
|
// 关闭自己的事件和socket
|
|
if (c->read_event)
|
|
{
|
|
eloop_remove_event(c->read_event);
|
|
c->read_event = NULL;
|
|
}
|
|
if (c->write_event)
|
|
{
|
|
eloop_remove_event(c->write_event);
|
|
c->write_event = NULL;
|
|
}
|
|
c->running = 0;
|
|
_os_printf("close sess:%x\r\n", (int) sess);
|
|
if (sess)
|
|
{
|
|
// sess->conn = NULL;
|
|
_os_printf("close sess->close:%x\r\n", (int) sess->closed);
|
|
sess->closed(sess, NULL);
|
|
}
|
|
// 没有sess,说明连接还没有正式
|
|
else
|
|
{
|
|
_os_printf("%s:%d\n", __FUNCTION__, __LINE__);
|
|
drop_conn(c);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
c->req_len += ret;
|
|
|
|
if (c->req_len == sizeof(c->req_buf) - 1)
|
|
{
|
|
spook_log(SL_VERBOSE, "malformed request from client; exceeded maximum size");
|
|
|
|
return;
|
|
}
|
|
|
|
c->req_buf[c->req_len] = 0;
|
|
while ((ret = parse_client_data(c)) > 0)
|
|
;
|
|
if (ret < 0)
|
|
{
|
|
_os_printf("%s:%d\n", __FUNCTION__, __LINE__);
|
|
// drop_conn( c );
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
extern int g_timeout;
|
|
uint8_t sta_mac[8];
|
|
|
|
extern uint8_t keep_send;
|
|
static void do_accept(void *ei, void *d)
|
|
{
|
|
spook_log(SL_DEBUG, "tcp do_accept");
|
|
struct listener *listener = (struct listener *) d;
|
|
int fd;
|
|
unsigned int i;
|
|
struct sockaddr_in addr;
|
|
struct conn *c;
|
|
|
|
_os_printf("%s %d\n", __func__, __LINE__);
|
|
i = sizeof(addr);
|
|
if ((fd = accept(listener->fd, (struct sockaddr *) &addr, &i)) < 0)
|
|
{
|
|
spook_log(SL_WARN, "error accepting TCP connection: %s", strerror(get_errno()));
|
|
return;
|
|
}
|
|
spook_log(SL_VERBOSE, "accepted connection from %s:%d", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
|
|
|
|
if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
|
|
{
|
|
spook_log(SL_INFO, "error setting O_NONBLOCK on socket: %s", strerror(get_errno()));
|
|
}
|
|
|
|
i = 0;
|
|
if (setsockopt(fd, IPPROTO_TCP /*SOL_SOCKET*/ /*SOL_TCP*/, TCP_NODELAY, &i, sizeof(i)) < 0)
|
|
{
|
|
spook_log(SL_INFO, "error setting TCP_NODELAY on socket: %s", strerror(get_errno()));
|
|
}
|
|
|
|
// int tos = 0xe0;
|
|
// setsockopt(fd, IPPROTO_IP, IP_TOS, (void *)&tos , sizeof(tos));
|
|
|
|
#if 0
|
|
/* Find the dhcp Offered Addr based the IP Addr of this Connection */
|
|
p_dhcp_addr = find_lease_by_yiaddr(addr.sin_addr.s_addr);
|
|
|
|
_os_printf("%s %d\n",__func__,__LINE__);
|
|
if (NULL != p_dhcp_addr)
|
|
{
|
|
for (c = conn_list; c != NULL; c = c->next)
|
|
{
|
|
ret = memcmp(c->chaddr, p_dhcp_addr->chaddr, 6);
|
|
if (0 == ret)
|
|
{
|
|
/* If the same Connection Client Mac Addr has existed, delete the previous Connection */
|
|
if (g_timeout == 0)
|
|
{
|
|
//parse_client_data(c);
|
|
if(c->sess)
|
|
c->sess->closed( c->sess, NULL);
|
|
|
|
}
|
|
else
|
|
{
|
|
g_timeout = 0;
|
|
}
|
|
|
|
drop_conn(c);
|
|
break;//只有一个ip是一样的,直接退出,否则drop_conn会更改conn_list链表,导致这里for出错
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
#endif
|
|
int keepalive = 1;
|
|
int keepidle = 10;
|
|
int keepintvl = 3;
|
|
int keepcnt = 3;
|
|
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *) &keepalive, sizeof(keepalive));
|
|
setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, (void *) &keepidle, sizeof(keepidle));
|
|
setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, (void *) &keepintvl, sizeof(keepintvl));
|
|
setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, (void *) &keepcnt, sizeof(keepcnt));
|
|
|
|
c = (struct conn *) malloc(sizeof(struct conn));
|
|
_os_printf("%s c:%X\n", __FUNCTION__, (int) c);
|
|
c->next = conn_list;
|
|
if (c->next)
|
|
{
|
|
c->next->prev = c;
|
|
}
|
|
c->prev = NULL;
|
|
c->fd = fd;
|
|
c->client_addr = addr;
|
|
c->proto = CONN_PROTO_START;
|
|
c->req_len = 0;
|
|
c->req_list = NULL;
|
|
c->read_event = eloop_add_fd(fd, EVENT_READ, EVENT_F_ENABLED, do_read, c);
|
|
c->write_event = eloop_add_fd(fd, EVENT_WRITE, EVENT_F_DISABLED, conn_write, c);
|
|
eloop_set_event_enabled(c->write_event, EVENT_F_DISABLED);
|
|
c->send_buf_r = c->send_buf_w = 0;
|
|
c->drop_after = 0;
|
|
c->proto_state = NULL;
|
|
c->sess = NULL; /* should be initialized by NULL */
|
|
c->running = 1;
|
|
os_event_init(&c->evt);
|
|
os_event_set(&c->evt, RTSP_TCP_READ_MUTEX | RTSP_TCP_WRITE_MUTEX, NULL);
|
|
conn_list = c;
|
|
|
|
/* Store the Client MAC Addr */
|
|
// memcpy(c->chaddr, p_dhcp_addr->chaddr, 6);
|
|
|
|
// memcpy(sta_mac, p_dhcp_addr->chaddr, 6);
|
|
//_os_printf("STA con[%x %x %x %x %x %x]\n",sta_mac[0],sta_mac[1],sta_mac[2],sta_mac[3],sta_mac[4],sta_mac[5]);
|
|
|
|
spook_log(SL_DEBUG, "TCP do_accept %d", fd);
|
|
}
|
|
|
|
static int tcp_listen(int port)
|
|
{
|
|
struct sockaddr_in addr;
|
|
struct listener *listener;
|
|
int opt, fd;
|
|
|
|
addr.sin_family = AF_INET;
|
|
addr.sin_addr.s_addr = 0;
|
|
addr.sin_port = htons(port);
|
|
|
|
if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
|
|
{
|
|
spook_log(SL_ERR, "error creating listen socket: %s", strerror(get_errno()));
|
|
return -1;
|
|
}
|
|
opt = 1;
|
|
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
|
|
{
|
|
spook_log(SL_WARN, "ignoring error on setsockopt: %s", strerror(get_errno()));
|
|
}
|
|
if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0)
|
|
{
|
|
spook_log(SL_ERR, "unable to bind to tcp socket: %s", strerror(get_errno()));
|
|
close(fd);
|
|
return -1;
|
|
}
|
|
if (listen(fd, 5) < 0)
|
|
{
|
|
spook_log(SL_ERR, "error when attempting to listen on tcp socket: %s", strerror(get_errno()));
|
|
close(fd);
|
|
return -1;
|
|
}
|
|
|
|
listener = (struct listener *) malloc(sizeof(struct listener));
|
|
listener->fd = fd;
|
|
|
|
eloop_add_fd(fd, EVENT_READ, EVENT_F_ENABLED, do_accept, listener);
|
|
|
|
spook_log(SL_INFO, "listening on tcp port %d", port);
|
|
_os_printf("port:%d\tfd:%d\n", port, fd);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/********************* GLOBAL CONFIGURATION DIRECTIVES ********************/
|
|
|
|
int config_port(int port)
|
|
{
|
|
if (port <= 0 || port > 65535)
|
|
{
|
|
spook_log(SL_ERR, "invalid listen port %d", port);
|
|
return -1;
|
|
}
|
|
|
|
return tcp_listen(port); // listen the 7070 port everytime
|
|
}
|