diff --git a/trunk/configure b/trunk/configure index 7d58bb896..e850a4bee 100755 --- a/trunk/configure +++ b/trunk/configure @@ -40,7 +40,7 @@ clean: server: _prepare_dir @echo "build the srs(simple rtmp server) over st(state-threads)" - \$(MAKE) -f ${GLOBAL_DIR_OBJS}/${GLOBAL_FILE_MAKEFILE} server + \$(MAKE) -f ${GLOBAL_DIR_OBJS}/${GLOBAL_FILE_MAKEFILE} simple_rtmp_server # the ./configure will generate it. _prepare_dir: @@ -68,7 +68,7 @@ GCC = g++ LINK = \$(GCC) AR = ar -.PHONY: default server +.PHONY: default simple_rtmp_server default: @@ -82,7 +82,7 @@ LibSTfile="${LibSTRoot}/libst.a" MODULE_ID="CORE" MODULE_DEPENDS=() ModuleLibIncs=(${LibSTRoot}) -MODULE_FILES=("srs_core" "srs_core_log" "srs_core_server" "srs_core_error") +MODULE_FILES=("srs_core" "srs_core_log" "srs_core_server" "srs_core_error" "srs_core_conn") MODULE_DIR="src/core" . auto/modules.sh CORE_OBJS="${MODULE_OBJS[@]}" @@ -100,7 +100,7 @@ MAIN_ENTRANCES=("srs_main_server") # srs(simple rtmp server) over st(state-threads) ModuleLibFiles=(${LibSTfile}) MODULE_OBJS="${CORE_OBJS[@]} ${CONFIG_OBJS[@]} ${PROTOCOL_OBJS[@]} ${MAIN_OBJS[@]}" -BUILD_KEY="server" APP_MAIN="srs_main_server" APP_NAME="server" LINK_OPTIONS="-ldl" SO_PATH="" . auto/apps.sh +BUILD_KEY="simple_rtmp_server" APP_MAIN="srs_main_server" APP_NAME="simple_rtmp_server" LINK_OPTIONS="-ldl" SO_PATH="" . auto/apps.sh echo 'configure ok! ' diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index da153a23d..ab4327437 100755 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -35,4 +35,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define __STDC_FORMAT_MACROS #endif +#include +#define SrsAssert(expression) assert(expression) + #endif \ No newline at end of file diff --git a/trunk/src/core/srs_core_conn.cpp b/trunk/src/core/srs_core_conn.cpp new file mode 100755 index 000000000..865067325 --- /dev/null +++ b/trunk/src/core/srs_core_conn.cpp @@ -0,0 +1,88 @@ +/* +The MIT License (MIT) + +Copyright (c) 2013 winlin + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include + +#include +#include +#include + +SrsConnection::SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd) +{ + server = srs_server; + stfd = client_stfd; +} + +SrsConnection::~SrsConnection() +{ +} + +int SrsConnection::start() +{ + int ret = ERROR_SUCCESS; + + if (st_thread_create(cycle_thread, this, 0, 0) == NULL) { + ret = ERROR_ST_CREATE_CYCLE_THREAD; + SrsError("st_thread_create conn cycle thread error. ret=%d", ret); + return ret; + } + SrsVerbose("create st conn cycle thread success."); + + return ret; +} + +int SrsConnection::do_cycle() +{ + int ret = ERROR_SUCCESS; + return ret; +} + +void SrsConnection::cycle() +{ + int ret = ERROR_SUCCESS; + + ret = do_cycle(); + + // success. + if (ret == ERROR_SUCCESS) { + SrsInfo("client process normally finished. ret=%d", ret); + } + + // client close peer. + if (ret == ERROR_SOCKET_CLOSED) { + SrsTrace("client disconnect peer. ret=%d", ret); + } + + server->remove(this); +} + +void* SrsConnection::cycle_thread(void* arg) +{ + SrsConnection* conn = (SrsConnection*)arg; + SrsAssert(conn != NULL); + + conn->cycle(); + + return NULL; +} + diff --git a/trunk/src/core/srs_core_conn.hpp b/trunk/src/core/srs_core_conn.hpp new file mode 100755 index 000000000..054d30511 --- /dev/null +++ b/trunk/src/core/srs_core_conn.hpp @@ -0,0 +1,52 @@ +/* +The MIT License (MIT) + +Copyright (c) 2013 winlin + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef SRS_CORE_CONN_HPP +#define SRS_CORE_CONN_HPP + +/* +#include +*/ + +#include + +#include + +class SrsServer; +class SrsConnection +{ +private: + SrsServer* server; + st_netfd_t stfd; +public: + SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd); + virtual ~SrsConnection(); +public: + virtual int start(); +private: + virtual int do_cycle(); + virtual void cycle(); + static void* cycle_thread(void* arg); +}; + +#endif \ No newline at end of file diff --git a/trunk/src/core/srs_core_error.hpp b/trunk/src/core/srs_core_error.hpp index a69b75521..a6d78fa2e 100755 --- a/trunk/src/core/srs_core_error.hpp +++ b/trunk/src/core/srs_core_error.hpp @@ -28,9 +28,20 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include */ -#define ERROR_SUCCESS 0 +#include -#define ERROR_ST_SET_EPOLL 100 -#define ERROR_ST_INITIALIZE 101 +#define ERROR_SUCCESS 0 + +#define ERROR_ST_SET_EPOLL 100 +#define ERROR_ST_INITIALIZE 101 +#define ERROR_ST_OPEN_SOCKET 102 +#define ERROR_ST_CREATE_LISTEN_THREAD 103 +#define ERROR_ST_CREATE_CYCLE_THREAD 104 + +#define ERROR_SOCKET_CREATE 200 +#define ERROR_SOCKET_SETREUSE 201 +#define ERROR_SOCKET_BIND 202 +#define ERROR_SOCKET_LISTEN 203 +#define ERROR_SOCKET_CLOSED 204 #endif \ No newline at end of file diff --git a/trunk/src/core/srs_core_server.cpp b/trunk/src/core/srs_core_server.cpp index 934a68078..f721b0e7c 100755 --- a/trunk/src/core/srs_core_server.cpp +++ b/trunk/src/core/srs_core_server.cpp @@ -21,12 +21,21 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include + +#include +#include +#include + +#include + #include #include #include +#include -#include +#define SERVER_LISTEN_BACKLOG 10 SrsServer::SrsServer() { @@ -34,6 +43,11 @@ SrsServer::SrsServer() SrsServer::~SrsServer() { + for (std::vector::iterator it = conns.begin(); it != conns.end(); ++it) { + SrsConnection* conn = *it; + delete conn; + } + conns.clear(); } int SrsServer::initialize() @@ -46,14 +60,14 @@ int SrsServer::initialize() SrsError("st_set_eventsys use linux epoll failed. ret=%d", ret); return ret; } - SrsInfo("st_set_eventsys use linux epoll success"); + SrsVerbose("st_set_eventsys use linux epoll success"); if(st_init() != 0){ ret = ERROR_ST_INITIALIZE; SrsError("st_init failed. ret=%d", ret); return ret; } - SrsTrace("st_init success"); + SrsVerbose("st_init success"); // set current log id. log_context->SetId(); @@ -61,3 +75,129 @@ int SrsServer::initialize() return ret; } + +int SrsServer::start(int port) +{ + int ret = ERROR_SUCCESS; + + if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { + ret = ERROR_SOCKET_CREATE; + SrsError("create linux socket error. ret=%d", ret); + return ret; + } + SrsVerbose("create linux socket success. fd=%d", fd); + + int reuse_socket = 1; + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_socket, sizeof(int)) == -1) { + ret = ERROR_SOCKET_SETREUSE; + SrsError("setsockopt reuse-addr error. ret=%d", ret); + return ret; + } + SrsVerbose("setsockopt reuse-addr success. fd=%d", fd); + + sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = INADDR_ANY; + if (bind(fd, (const sockaddr*)&addr, sizeof(sockaddr_in)) == -1) { + ret = ERROR_SOCKET_BIND; + SrsError("bind socket error. ret=%d", ret); + return ret; + } + SrsVerbose("bind socket success. fd=%d", fd); + + if (listen(fd, SERVER_LISTEN_BACKLOG) == -1) { + ret = ERROR_SOCKET_LISTEN; + SrsError("listen socket error. ret=%d", ret); + return ret; + } + SrsVerbose("listen socket success. fd=%d", fd); + + if ((stfd = st_netfd_open_socket(fd)) == NULL){ + ret = ERROR_ST_OPEN_SOCKET; + SrsError("st_netfd_open_socket open socket failed. ret=%d", ret); + return ret; + } + SrsVerbose("st open socket success. fd=%d", fd); + + if (st_thread_create(listen_thread, this, 0, 0) == NULL) { + ret = ERROR_ST_CREATE_LISTEN_THREAD; + SrsError("st_thread_create listen thread error. ret=%d", ret); + return ret; + } + SrsVerbose("create st listen thread success."); + + SrsTrace("server started, listen at port=%d, fd=%d", port, fd); + + return ret; +} + +int SrsServer::cycle() +{ + int ret = ERROR_SUCCESS; + st_thread_exit(NULL); + return ret; +} + +void SrsServer::remove(SrsConnection* conn) +{ + std::vector::iterator it = std::find(conns.begin(), conns.end(), conn); + + if (it != conns.end()) { + conns.erase(it); + } + + // all connections are created by server, + // so we delete it here. + delete conn; +} + +int SrsServer::accept_client(st_netfd_t client_stfd) +{ + int ret = ERROR_SUCCESS; + + SrsConnection* conn = new SrsConnection(this, client_stfd); + + // directly enqueue, the cycle thread will remove the client. + conns.push_back(conn); + + // cycle will start process thread and when finished remove the client. + if ((ret = conn->start()) != ERROR_SUCCESS) { + return ret; + } + + return ret; +} + +void SrsServer::listen_cycle() +{ + int ret = ERROR_SUCCESS; + + while (true) { + st_netfd_t client_stfd = st_accept(stfd, NULL, NULL, ST_UTIME_NO_TIMEOUT); + + if(client_stfd == NULL){ + // ignore error. + SrsWarn("ignore accept thread stoppped for accept client error"); + continue; + } + + if ((ret = accept_client(client_stfd)) != ERROR_SUCCESS) { + SrsWarn("accept client error. ret=%d", ret); + continue; + } + + SrsVerbose("accept client finished. ret=%d", ret); + } +} + +void* SrsServer::listen_thread(void* arg) +{ + SrsServer* server = (SrsServer*)arg; + SrsAssert(server != NULL); + + server->listen_cycle(); + + return NULL; +} + diff --git a/trunk/src/core/srs_core_server.hpp b/trunk/src/core/srs_core_server.hpp index 01af144e7..599775765 100755 --- a/trunk/src/core/srs_core_server.hpp +++ b/trunk/src/core/srs_core_server.hpp @@ -28,13 +28,31 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include */ +#include + +#include + +#include + +class SrsConnection; class SrsServer { +private: + int fd; + st_netfd_t stfd; + std::vector conns; public: SrsServer(); virtual ~SrsServer(); public: virtual int initialize(); + virtual int start(int port); + virtual int cycle(); + virtual void remove(SrsConnection* conn); +private: + virtual int accept_client(st_netfd_t client_stfd); + virtual void listen_cycle(); + static void* listen_thread(void* arg); }; #endif \ No newline at end of file diff --git a/trunk/src/main/srs_main_server.cpp b/trunk/src/main/srs_main_server.cpp index 31c830940..548022706 100755 --- a/trunk/src/main/srs_main_server.cpp +++ b/trunk/src/main/srs_main_server.cpp @@ -36,5 +36,13 @@ int main(int /*argc*/, char** /*argv*/){ return ret; } + if ((ret = server.start(19350)) != ERROR_SUCCESS) { + return ret; + } + + if ((ret = server.cycle()) != ERROR_SUCCESS) { + return ret; + } + return 0; } diff --git a/trunk/src/srs/srs.upp b/trunk/src/srs/srs.upp index de51d1711..cd84fb5ac 100755 --- a/trunk/src/srs/srs.upp +++ b/trunk/src/srs/srs.upp @@ -8,6 +8,8 @@ file ..\core\srs_core_error.cpp, ..\core\srs_core_server.hpp, ..\core\srs_core_server.cpp, + ..\core\srs_core_conn.hpp, + ..\core\srs_core_conn.cpp, ..\core\srs_core_log.hpp, ..\core\srs_core_log.cpp; mainconfig