├── .gitattributes ├── .github └── workflows │ └── docker-image.yml ├── .gitignore ├── Dockerfile ├── Makefile ├── README.md ├── build_srt.bat ├── doc └── Directives.md ├── obj └── README.md ├── sls.conf ├── slscore ├── HttpClient.cpp ├── HttpClient.hpp ├── HttpRoleList.cpp ├── HttpRoleList.hpp ├── README.md ├── SLSArray.cpp ├── SLSArray.hpp ├── SLSClient.cpp ├── SLSClient.hpp ├── SLSEpollThread.cpp ├── SLSEpollThread.hpp ├── SLSGroup.cpp ├── SLSGroup.hpp ├── SLSListener.cpp ├── SLSListener.hpp ├── SLSLock.hpp ├── SLSLog.cpp ├── SLSLog.hpp ├── SLSManager.cpp ├── SLSManager.hpp ├── SLSMapData.cpp ├── SLSMapData.hpp ├── SLSMapPublisher.cpp ├── SLSMapPublisher.hpp ├── SLSMapRelay.cpp ├── SLSMapRelay.hpp ├── SLSPlayer.cpp ├── SLSPlayer.hpp ├── SLSPublisher.cpp ├── SLSPublisher.hpp ├── SLSPuller.cpp ├── SLSPuller.hpp ├── SLSPullerManager.cpp ├── SLSPullerManager.hpp ├── SLSPusher.cpp ├── SLSPusher.hpp ├── SLSPusherManager.cpp ├── SLSPusherManager.hpp ├── SLSRecycleArray.cpp ├── SLSRecycleArray.hpp ├── SLSRelay.cpp ├── SLSRelay.hpp ├── SLSRelayManager.cpp ├── SLSRelayManager.hpp ├── SLSRole.cpp ├── SLSRole.hpp ├── SLSRoleList.cpp ├── SLSRoleList.hpp ├── SLSSrt.cpp ├── SLSSrt.hpp ├── SLSSyncClock.cpp ├── SLSSyncClock.hpp ├── SLSThread.cpp ├── SLSThread.hpp ├── TCPRole.cpp ├── TCPRole.hpp ├── TSFileTimeReader.cpp ├── TSFileTimeReader.hpp ├── common.cpp ├── common.hpp ├── conf.cpp ├── conf.hpp ├── httplib.h └── json.hpp ├── srt-live-client.cpp ├── srt-live-server.cpp ├── start_srt.bat └── stop_srt.bat /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/workflows/docker-image.yml: -------------------------------------------------------------------------------- 1 | name: CI to Docker Hub 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | 7 | jobs: 8 | 9 | build: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | 14 | - name: Check Out Repo 15 | uses: actions/checkout@v2 16 | 17 | - name: Login to Docker Hub 18 | uses: docker/login-action@v1 19 | with: 20 | username: ${{ secrets.DOCKER_HUB_USERNAME }} 21 | password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} 22 | 23 | - name: Set up Docker Buildx 24 | id: buildx 25 | uses: docker/setup-buildx-action@v1 26 | 27 | - name: Build and push 28 | id: docker_build 29 | uses: docker/build-push-action@v2 30 | with: 31 | context: ./ 32 | file: ./Dockerfile 33 | push: true 34 | tags: ${{ secrets.DOCKER_HUB_USERNAME }}/sls-b3ck-edit:latest 35 | 36 | - name: Image digest 37 | run: echo ${{ steps.docker_build.outputs.digest }} 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | obj/*.o 3 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # build stage 2 | FROM alpine:latest as build 3 | RUN apk update &&\ 4 | apk upgrade &&\ 5 | apk add --no-cache linux-headers alpine-sdk cmake tcl openssl-dev zlib-dev 6 | WORKDIR /tmp 7 | COPY . /tmp/srt-live-server/ 8 | RUN git clone https://github.com/Haivision/srt.git 9 | WORKDIR /tmp/srt 10 | RUN git checkout master && ./configure && make -j8 && make install 11 | WORKDIR /tmp/srt-live-server 12 | RUN make -j8 13 | 14 | # final stage 15 | FROM alpine:latest 16 | ENV LD_LIBRARY_PATH /lib:/usr/lib:/usr/local/lib64 17 | RUN apk update &&\ 18 | apk upgrade &&\ 19 | apk add --no-cache openssl libstdc++ &&\ 20 | adduser -D srt &&\ 21 | mkdir /etc/sls /logs &&\ 22 | chown srt /logs 23 | COPY --from=build /usr/local/bin/srt-* /usr/local/bin/ 24 | COPY --from=build /usr/local/lib/libsrt* /usr/local/lib/ 25 | COPY --from=build /tmp/srt-live-server/bin/* /usr/local/bin/ 26 | COPY sls.conf /etc/sls/ 27 | VOLUME /logs 28 | EXPOSE 8181 30000/udp 29 | USER srt 30 | WORKDIR /home/srt 31 | ENTRYPOINT [ "sls", "-c", "/etc/sls/sls.conf"] 32 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL = /bin/sh 2 | MAIN_NAME=sls 3 | CLIENT_NAME=slc 4 | INC_PATH = -I./ -I../ -I./slscore -I./include 5 | LIB_PATH = -L ./lib 6 | LIBRARY_FILE = -lpthread -lz -lsrt 7 | BIN_PATH = ./bin 8 | 9 | DEBUG = -g 10 | CFLAGS += $(DEBUG) -w -fcompare-debug-second 11 | 12 | LOG_PATH = ./logs 13 | 14 | 15 | OUTPUT_PATH = ./obj 16 | OBJS = $(OUTPUT_PATH)/SLSLog.o \ 17 | $(OUTPUT_PATH)/common.o\ 18 | $(OUTPUT_PATH)/conf.o\ 19 | $(OUTPUT_PATH)/SLSThread.o\ 20 | $(OUTPUT_PATH)/SLSEpollThread.o\ 21 | $(OUTPUT_PATH)/SLSManager.o\ 22 | $(OUTPUT_PATH)/SLSGroup.o\ 23 | $(OUTPUT_PATH)/SLSRole.o\ 24 | $(OUTPUT_PATH)/SLSListener.o\ 25 | $(OUTPUT_PATH)/SLSRoleList.o\ 26 | $(OUTPUT_PATH)/SLSSrt.o\ 27 | $(OUTPUT_PATH)/SLSPublisher.o\ 28 | $(OUTPUT_PATH)/SLSPlayer.o\ 29 | $(OUTPUT_PATH)/SLSRecycleArray.o\ 30 | $(OUTPUT_PATH)/SLSMapData.o\ 31 | $(OUTPUT_PATH)/SLSMapPublisher.o\ 32 | $(OUTPUT_PATH)/SLSRelay.o\ 33 | $(OUTPUT_PATH)/SLSPuller.o\ 34 | $(OUTPUT_PATH)/SLSPusher.o\ 35 | $(OUTPUT_PATH)/SLSRelayManager.o\ 36 | $(OUTPUT_PATH)/SLSPullerManager.o\ 37 | $(OUTPUT_PATH)/SLSPusherManager.o\ 38 | $(OUTPUT_PATH)/SLSMapRelay.o\ 39 | $(OUTPUT_PATH)/SLSClient.o\ 40 | $(OUTPUT_PATH)/TCPRole.o\ 41 | $(OUTPUT_PATH)/SLSArray.o\ 42 | $(OUTPUT_PATH)/HttpRoleList.o\ 43 | $(OUTPUT_PATH)/HttpClient.o\ 44 | $(OUTPUT_PATH)/SLSSyncClock.o\ 45 | $(OUTPUT_PATH)/TSFileTimeReader.o 46 | 47 | CORE_PATH = slscore 48 | COMMON_FILES = common.hpp 49 | 50 | all: $(OBJS) 51 | mkdir -p ${LOG_PATH} 52 | mkdir -p ${OUTPUT_PATH} 53 | mkdir -p ${BIN_PATH} 54 | ${CXX} -o ${BIN_PATH}/${MAIN_NAME} srt-live-server.cpp $(OBJS) $(CFLAGS) $(INC_PATH) $(LIB_PATH) $(LIBRARY_FILE) 55 | ${CXX} -o ${BIN_PATH}/${CLIENT_NAME} srt-live-client.cpp $(OBJS) $(CFLAGS) $(INC_PATH) $(LIB_PATH) $(LIBRARY_FILE) 56 | #******************************************************************************# 57 | # Build successful ! # 58 | #******************************************************************************# 59 | 60 | $(OUTPUT_PATH)/%.o: ./$(CORE_PATH)/%.cpp 61 | ${CXX} -c $(CFLAGS) $< -o $@ $(INC_FLAGS) 62 | 63 | clean: 64 | rm -f $(OUTPUT_PATH)/*.o 65 | rm -rf $(BIN_PATH)/* 66 | 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Why? 2 | ============ 3 | To streamline an SRT solution for the IRL community, with NOALBS(https://b3ck.com/noalbs) setup to work specifically with this SRT Solution you have one of the most reliable IRL stream recovery systems that you can run on your own. 4 | 5 | Starting Notes: 6 | ============ 7 | - Cloned from https://gitlab.com/mattwb65/srt-live-server 8 | - Edited by b3ck for the IRL Community (Added Credits & Links during server bootup to help others) 9 | - This readme only covers Docker Desktop for Windows, but may have similarities to other Operating Systems but it's not intended. 10 | 11 | 12 | Introduction: 13 | ============ 14 | srt-live-server(SLS) is an open source live streaming server for low latency based on Secure Reliable Transport (SRT). 15 | Normally, the latency of transport by SLS is less than 1 second in internet. 16 | 17 | 18 | Requirements: 19 | ============ 20 | Install Docker >> https://docs.docker.com/get-docker/ 21 | 22 | Command Line Alternative: 23 | ============ 24 | If you don't want to use the Docker Desktop you can alternatively run this command after installing docker: 25 | ``` 26 | docker run -d -p 30000:30000/udp -p 8181:8181/tcp --name=sls-b3ck-edit --restart=always --pull=always -v sls-b3ck-edit_data:/data b3ckontwitch/sls-b3ck-edit 27 | ``` 28 | 29 | Install Instructions (Using Docker Desktop): 30 | ============ 31 | - Run this command in a Command window or PowerShell: `docker pull b3ckontwitch/sls-b3ck-edit` 32 | - Open your Docker Dashboard, click on Images on the left and you should see `b3ckontwitch/sls-b3ck-edit` listed. 33 | - Hover over the `b3ckontwitch/sls-b3ck-edit` image you should see a `RUN` button on the right, hit the `RUN` button. 34 | - A `New Container` window will pop-up; 35 | > - Click on optional settings. 36 | > - Give the container any name you want. 37 | > - For the Ports section just match the local host ports with the container ports; 38 | > - You'll need to click the (+) button to add the `8181` web server port. 39 | 40 | > - New Container Configuration Control: 41 | > - If you want to be able to change your configuration settings, like ports and streamid(s), you'll need to make a directory on your computer and put the `sls.conf` in the directory then match it up with a volume in the container and have it point to `/ETC/SLS`. 42 | 43 | > - If you will be using a custom `sls.conf` then you'll need to make one and put it in that directory you just made on your computer, here is an example of what should be in it; 44 | 45 | ``` 46 | srt { 47 | worker_threads 1; # Usually don't need to touch this 48 | worker_connections 300; # or this... 49 | 50 | http_port 8181; # HTTP Port for viewing your stats, ex; http://127.0.0.1:8181/stats, useful for 3rd Party Applications. 51 | cors_header *; # Used for 3rd party applications, so you can pull data into them. 52 | 53 | log_file logs/error.log; # Log file location, if you have errors, look here. 54 | log_level info; # Log Level 55 | 56 | record_hls_path_prefix /tmp/mov/sls; # If you want HLS, this is the HLS location. 57 | 58 | server { 59 | listen 30000; # The port that SRT will listen on, don't forget to forward your ports! 60 | latency 1000; # Match this with your Client/Encoder, the lower this is then the less lag, but it could cause missed frames and pixelation, 61 | # in unstable conditions, You can go all the way up to 5000 with latency, which will usually help during unstable conditions, but induce lag. 62 | 63 | # This is what determines your "play" URL.. 64 | domain_player play; # if this was set to "view" your player URL would be for example; view/live/feed1 65 | 66 | # This is what determines your "publish" URL.. 67 | domain_publisher publish; # if this was set to "give" your publish URL would be for example; give/live/feed1 68 | 69 | default_sid publish/live/feed1; # If your SRT client/encoder doesn't support streamid, this will be the default. 70 | 71 | backlog 100; # Accept connections at the same time. 72 | idle_streams_timeout 3; # How many seconds until streams are considered idle and then closed. 73 | 74 | 75 | app { 76 | app_player live; # Name of your player URL, ex; if this was set to "remote" the play URL would be; play/remote/cam1 77 | app_publisher live; # Name of your publisher URL, ex; if this was set to "access" the publish URL would be; publish/access/cam1 78 | 79 | record_hls off; # Turn HLS on/off 80 | record_hls_segment_duration 10; # How long in seconds you want the HSL segments to be. 81 | 82 | } 83 | } 84 | } 85 | ``` 86 | 87 | > - If you don't change the config these defaults are as follows: 88 | > - SRT Port: `30000` 89 | > - OBS Play URL: `srt://:?streamid=play/live/feed1` 90 | > - Client Publish URL: `srt://:?streamid=publish/live/feed1` 91 | > - Example Client Publish URL: `srt://255.255.255.255:30000?streamid=publish/live/feed1` 92 | 93 | - After you figured out the way you want to manage your configuration click on the blue `RUN` button to add the image to a docker container. 94 | 95 | 96 | > - You could also install 'Microsoft Code' >> https://code.visualstudio.com/download , then install the Docker Extension and then browse/edit/save the `sls.conf`, please keep in mind you can only browse/edit/save files in a Docker Container while it's running: 97 | 98 | > ![image](https://user-images.githubusercontent.com/1740542/110266056-a378a180-7f82-11eb-8806-c1cf968dc30f.png) 99 | 100 | Viewing your SRT stream in OBS: 101 | ============ 102 | OBS supports SRT protocol to view stream when version is later than v25.0. you can use the following URL in media source: 103 | 104 | `srt://:?streamid=play/live/feed1` 105 | example: `srt://127.0.0.1:30000?streamid=play/live/feed1` 106 | 107 | ![image](https://user-images.githubusercontent.com/1740542/110401480-4262d380-803f-11eb-96f7-8c1760010d00.png) 108 | 109 | Things to Know: 110 | https://apps.apple.com/us/app/larix-broadcaster/id1042474385 111 | 112 | 1.) SLS refers to the RTMP URL format(domain/app/stream_name), example: publish/live/feed1. The URL of SLS must be set in streamid parameter of SRT, which will be the unique identification a stream. 113 | 114 | 2.) How to distinguish the publisher and player of the same stream? In conf file, you can set parameters of domain_player/domain_publisher and app_player/app_publisher to resolve it. Importantly, the two combination strings of domain_publisher/app_publisher and domain_player/app_player must not be equal in the same server block. 115 | 116 | 3.) There is an APP you can use on your phone to stream to your SRT server: 117 | - Android: https://play.google.com/store/apps/details?id=com.wmspanel.larix_broadcaster 118 | - Apple: https://apps.apple.com/us/app/larix-broadcaster/id1042474385 119 | 120 | VMware - Docker Desktop Prerequisites (Provided by: Th3GamerVerse) 121 | ============ 122 | If you want to use Docker inside a VMWare Virtual Machine follow these steps: 123 | 124 | 1.) (In VMWare) Make sure the Docker VM BIOS is set to allow virtualization: 125 | - a.) Shutdown the Docker VM (VM must be turned OFF) 126 | - b.) Right click the Docker VM and choose “Edit Settings” 127 | 128 | ![image](https://user-images.githubusercontent.com/1740542/132995110-b55bff56-3dc8-4400-bf01-e26c4e1335db.png) 129 | 130 | - c.) Expand CPU setting: 131 | 132 | ![image](https://user-images.githubusercontent.com/1740542/132995148-49cc26c3-7512-4e3a-8917-d10b9d2faef4.png) 133 | 134 | - d.) Select the “Expose hardware assisted virtualization to the guest OS” option: 135 | 136 | ![image](https://user-images.githubusercontent.com/1740542/132995189-231f2905-711a-4f59-a563-218105a1bbeb.png) 137 | 138 | - e.) Power the Docker VM back up and continue with the following steps. 139 | 140 | 2.) Run these commands in PowerShell (on the Docker VM): (May not be needed in all cases) 141 | - `Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All` 142 | - `Enable-WindowsOptionalFeature -Online -FeatureName Containers -All` 143 | 144 | 3.) Install: https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi 145 | 146 | 4.) Run this final command in PowerShell: 147 | - `wsl --set-default-version 2` 148 | 149 | 5.) After you have done all of this you should be able to install and run Docker Desktop in a Windows Virtual Machine using VMWare. 150 | 151 | 152 | Release Notes 153 | ============ 154 | v1.4.8-b (b3ck edit) 155 | --------------------------- 156 | 1. Now compatible with SRT Source v1.4.2 157 | 2. Added Credits and Resources for the IRL Community. 158 | 3. Edited `DockerFile` to `checkout` the `master` from the SRT Source. 159 | 4. Created Windows Batch Files to build and start the SLS `DockerFile`. 160 | 5. Added support for SRTLA connections. 161 | 162 | Contact / Support 163 | ============ 164 | If you have any issues feel free to message me on [discord](https://discordapp.com/channels/@me/96991451006660608) @ `b3ck#3517` 165 | -------------------------------------------------------------------------------- /build_srt.bat: -------------------------------------------------------------------------------- 1 | powershell -Command "docker build -t sls ." -------------------------------------------------------------------------------- /doc/Directives.md: -------------------------------------------------------------------------------- 1 | description for config file. 2 | 3 | https://github.com/Edward-Wu/srt-live-server/wiki/Directives 4 | -------------------------------------------------------------------------------- /obj/README.md: -------------------------------------------------------------------------------- 1 | obj files 2 | -------------------------------------------------------------------------------- /sls.conf: -------------------------------------------------------------------------------- 1 | srt { 2 | worker_threads 1; 3 | worker_connections 300 ; 4 | 5 | http_port 8181; 6 | cors_header *; 7 | 8 | log_file logs/error.log ; 9 | log_level info; 10 | 11 | record_hls_path_prefix /tmp/mov/sls; 12 | 13 | server { 14 | listen 30000; 15 | latency 1000; 16 | 17 | domain_player play; 18 | domain_publisher publish; 19 | 20 | default_sid publish/live/feed1; 21 | 22 | backlog 100; 23 | idle_streams_timeout 3; 24 | 25 | 26 | app { 27 | app_player live ; 28 | app_publisher live ; 29 | 30 | record_hls off; 31 | record_hls_segment_duration 10; 32 | 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /slscore/HttpClient.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2019-2020 Edward.Wu 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 7 | * this software and associated documentation files (the "Software"), to deal in 8 | * the Software without restriction, including without limitation the rights to 9 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 10 | * the Software, and to permit persons to whom the Software is furnished to do so, 11 | * subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef _HttpClient_INCLUDE_ 25 | #define _HttpClient_INCLUDE_ 26 | 27 | #include 28 | 29 | #include "TCPRole.hpp" 30 | #include "SLSArray.hpp" 31 | #include "common.hpp" 32 | 33 | enum HTTP_CALLBACK_TYPE { 34 | HCT_OPEN = 0, 35 | HCT_CLOSE, 36 | HCT_RESPONSE_END, 37 | HCT_REQUEST_CONTENT, 38 | }; 39 | 40 | #define HTTP_DATA_SIZE 4096 41 | #define SLS_HTTP_INVALID_CLIENT_ID 0 42 | #define HTTP_RESPONSE_CODE_200 "200" 43 | 44 | typedef int (*HTTP_CALLBACK)(void *p, HTTP_CALLBACK_TYPE type, void *v, void* context); 45 | typedef struct HTTP_RESPONSE_INFO { 46 | std::vector m_response_header; 47 | std::string m_response_code; 48 | std::string m_response_content; 49 | int m_response_content_length; 50 | }; 51 | /** 52 | * CHttpClient 53 | */ 54 | class CHttpClient : public CTCPRole 55 | { 56 | public : 57 | CHttpClient(); 58 | virtual ~CHttpClient(); 59 | 60 | int open(const char *url, const char *method=NULL, int interval=0); 61 | int close(); 62 | int reopen(); 63 | 64 | int send(); 65 | int recv(); 66 | virtual int handler(DATA_PARAM *p); 67 | virtual int handler(); 68 | 69 | void set_id(uint32_t client_id); 70 | void set_timeout(int v); 71 | void set_stage_callback(HTTP_CALLBACK callback, void *context); 72 | 73 | int check_timeout(int64_t cur_tm_ms=0); 74 | int check_repeat(int64_t cur_tm_ms=0); 75 | int check_finished(); 76 | 77 | uint32_t get_id(); 78 | HTTP_RESPONSE_INFO *get_response_info(); 79 | protected: 80 | uint32_t m_id; 81 | char m_url[URL_MAX_LEN]; 82 | char m_uri[URL_MAX_LEN]; 83 | char m_remote_host[URL_MAX_LEN]; 84 | char m_http_method[32]; 85 | int m_remote_port; 86 | int64_t m_begin_tm_ms; 87 | int64_t m_end_tm_ms; 88 | int m_timeout;//s 89 | int m_interval;//s 90 | 91 | CSLSArray m_out_array; 92 | uint8_t m_out_data[HTTP_DATA_SIZE]; 93 | int m_out_pos ; 94 | int m_out_data_len ; 95 | 96 | std::string m_request_data; 97 | 98 | HTTP_RESPONSE_INFO m_response_info; 99 | /* 100 | std::vector m_response_header; 101 | std::string m_response_code; 102 | std::string m_response_content; 103 | int m_response_content_length; 104 | */ 105 | HTTP_CALLBACK m_callback; 106 | void *m_callback_context; 107 | 108 | int parse_url(); 109 | int write_http_header(int data_len); 110 | int write_string(std::string *str); 111 | int parse_http_response(std::string &response); 112 | virtual int generate_http_request(); 113 | void get_request_data(); 114 | 115 | private: 116 | 117 | }; 118 | 119 | 120 | #endif 121 | -------------------------------------------------------------------------------- /slscore/HttpRoleList.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2019-2020 Edward.Wu 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 7 | * this software and associated documentation files (the "Software"), to deal in 8 | * the Software without restriction, including without limitation the rights to 9 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 10 | * the Software, and to permit persons to whom the Software is furnished to do so, 11 | * subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | 25 | 26 | #include "HttpRoleList.hpp" 27 | 28 | #include 29 | #include 30 | 31 | 32 | #include "SLSLog.hpp" 33 | #include "SLSLock.hpp" 34 | 35 | /** 36 | * CHttpRoleList class implementation 37 | */ 38 | 39 | CHttpRoleList::CHttpRoleList() 40 | { 41 | } 42 | CHttpRoleList::~CHttpRoleList() 43 | { 44 | } 45 | 46 | int CHttpRoleList::push(CHttpClient * role) 47 | { 48 | if (role) { 49 | CSLSLock lock(&m_mutex); 50 | m_list_role.push_back(role); 51 | } 52 | return 0; 53 | } 54 | 55 | CHttpClient * CHttpRoleList::pop() 56 | { 57 | CSLSLock lock(&m_mutex); 58 | CHttpClient * role = NULL; 59 | if (!m_list_role.empty()) { 60 | role = m_list_role.front(); 61 | m_list_role.pop_front(); 62 | } 63 | return role; 64 | } 65 | 66 | int CHttpRoleList::size() 67 | { 68 | CSLSLock lock(&m_mutex); 69 | return m_list_role.size(); 70 | } 71 | 72 | void CHttpRoleList::erase() 73 | { 74 | CSLSLock lock(&m_mutex); 75 | sls_log(SLS_LOG_TRACE, "[%p]CHttpRoleList::erase, list.count=%d", this, m_list_role.size()); 76 | for (std::list::iterator it = m_list_role.begin(); it != m_list_role.end();) 77 | { 78 | CHttpClient * role = *it; 79 | if (role) { 80 | role->close(); 81 | delete role; 82 | } 83 | it ++; 84 | } 85 | m_list_role.clear(); 86 | } 87 | 88 | -------------------------------------------------------------------------------- /slscore/HttpRoleList.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2019-2020 Edward.Wu 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 7 | * this software and associated documentation files (the "Software"), to deal in 8 | * the Software without restriction, including without limitation the rights to 9 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 10 | * the Software, and to permit persons to whom the Software is furnished to do so, 11 | * subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | 25 | 26 | #ifndef _HttpRoleList_INCLUDE_ 27 | #define _HttpRoleList_INCLUDE_ 28 | 29 | #include 30 | 31 | #include "HttpClient.hpp" 32 | #include "SLSLock.hpp" 33 | 34 | /** 35 | * CHttpRoleList 36 | */ 37 | class CHttpRoleList 38 | { 39 | public : 40 | CHttpRoleList(); 41 | ~CHttpRoleList(); 42 | 43 | int push(CHttpClient *role); 44 | CHttpClient *pop(); 45 | void erase(); 46 | int size(); 47 | 48 | protected: 49 | 50 | private: 51 | std::list m_list_role; 52 | CSLSMutex m_mutex; 53 | }; 54 | 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /slscore/README.md: -------------------------------------------------------------------------------- 1 | core file for srt-live-server 2 | -------------------------------------------------------------------------------- /slscore/SLSArray.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #include 27 | 28 | 29 | #include "SLSArray.hpp" 30 | #include "SLSLog.hpp" 31 | 32 | const int DEFAULT_MAX_DATA_SIZE = 4096;//about 5mbps*2sec 33 | 34 | CSLSArray::CSLSArray() 35 | { 36 | m_nDataSize = DEFAULT_MAX_DATA_SIZE; 37 | m_nWritePos = 0; 38 | m_nReadPos = 0; 39 | m_nDataCount = 0; 40 | m_arrayData = new uint8_t[m_nDataSize]; 41 | 42 | } 43 | 44 | CSLSArray::~CSLSArray() 45 | { 46 | CSLSLock lock(&m_mutex); 47 | if (m_arrayData != NULL) { 48 | delete[] m_arrayData; 49 | m_arrayData = NULL; 50 | } 51 | } 52 | 53 | int CSLSArray::count() 54 | { 55 | CSLSLock lock(&m_mutex); 56 | return m_nDataCount; 57 | } 58 | 59 | //please call this function before get and put, 60 | //if not, the read data will be make confusion. 61 | void CSLSArray::setSize(int n) 62 | { 63 | CSLSLock lock(&m_mutex); 64 | delete[] m_arrayData ; 65 | m_nDataSize = n; 66 | m_nWritePos = 0; 67 | m_nReadPos = 0; 68 | m_nDataCount = 0; 69 | m_arrayData = new uint8_t[m_nDataSize]; 70 | } 71 | 72 | void CSLSArray::clear() 73 | { 74 | m_nWritePos = 0; 75 | m_nReadPos = 0; 76 | m_nDataCount = 0; 77 | } 78 | 79 | int CSLSArray::put(const uint8_t * data, int len) 80 | { 81 | if (NULL == data || len <= 0) { 82 | sls_log(SLS_LOG_INFO, "[%p]CSLSArray::put, failed, data=%p, len=%d.", 83 | this, data, len); 84 | return SLS_ERROR; 85 | } 86 | 87 | CSLSLock lock(&m_mutex); 88 | 89 | int nRemainder = m_nDataSize - m_nDataCount; 90 | if (len > nRemainder) { 91 | //need expand data buff 92 | //ext at least DEFAULT_MAX_DATA_SIZE each time. 93 | int ext_len = m_nDataSize + (DEFAULT_MAX_DATA_SIZE>=len?DEFAULT_MAX_DATA_SIZE:len);//m_nDataCount + len; 94 | sls_log(SLS_LOG_INFO, "[%p]CSLSArray::put, len=%d is bigger than nRemainder=%d, ext m_nDataSize=%d to ext_len=%d.", 95 | this, data, len, m_nDataSize, ext_len); 96 | 97 | uint8_t *ext_data = new uint8_t[ext_len]; 98 | int re = get_inline(ext_data, m_nDataCount); 99 | memcpy(ext_data + re, data, len); 100 | delete[] m_arrayData; 101 | m_arrayData = ext_data; 102 | m_nDataSize = ext_len; 103 | m_nWritePos = 0; 104 | m_nReadPos = 0; 105 | m_nDataCount = re + len; 106 | return len; 107 | } 108 | 109 | 110 | if (m_nDataSize - m_nWritePos >= len) { 111 | //copy directly 112 | memcpy(m_arrayData + m_nWritePos, data, len); 113 | m_nWritePos += len; 114 | } else { 115 | int first_len = m_nDataSize - m_nWritePos; 116 | memcpy(m_arrayData + m_nWritePos, data, first_len); 117 | memcpy(m_arrayData, data + first_len, len - first_len); 118 | m_nWritePos = (len - first_len); 119 | } 120 | 121 | if (m_nWritePos==m_nDataSize) 122 | m_nWritePos = 0; 123 | 124 | //no consider int wrapround; 125 | m_nDataCount += len; 126 | sls_log(SLS_LOG_TRACE, "[%p]CSLSArray::put, len=%d, m_nWritePos=%d, m_nDataCount=%d, m_nDataSize=%d.", 127 | this, len, m_nWritePos, m_nDataCount, m_nDataSize); 128 | return len; 129 | } 130 | 131 | int CSLSArray::get(uint8_t *data, int size) 132 | { 133 | CSLSLock lock(&m_mutex); 134 | return get_inline(data, size); 135 | } 136 | 137 | int CSLSArray::get_inline(uint8_t *data, int size) 138 | { 139 | if (NULL == m_arrayData) { 140 | sls_log(SLS_LOG_INFO, "[%p]CSLSArray::get, failed, m_arrayData is NULL.", this); 141 | return SLS_ERROR; 142 | } 143 | 144 | if (0 == m_nDataCount) { 145 | sls_log(SLS_LOG_TRACE, "[%p]CSLSArray::get, no new data.", this); 146 | return SLS_OK; 147 | } 148 | sls_log(SLS_LOG_TRACE, "[%p]CSLSArray::get, m_nReadPos=%d, m_nWritePos=%d, m_nDataCount=%d, m_nDataSize=%d.", 149 | this, m_nReadPos, m_nWritePos, m_nDataCount, m_nDataSize); 150 | 151 | int ready_data_len = 0; 152 | int copy_data_len = 0; 153 | if (m_nReadPos < m_nWritePos) { 154 | //read pos is behind in the write pos 155 | ready_data_len = m_nWritePos - m_nReadPos; 156 | copy_data_len = ready_data_len <= size ? ready_data_len : size; 157 | //sls_log(SLS_LOG_TRACE, "[%p]CSLSArray::get, read pos is behind in the write pos, copy_data_len=%d, ready_data_len=%d, size=%d.", 158 | // this, copy_data_len, ready_data_len, size); 159 | memcpy(data, m_arrayData + m_nReadPos, copy_data_len); 160 | m_nReadPos += copy_data_len; 161 | m_nDataCount -= copy_data_len; 162 | } else { 163 | ready_data_len = m_nDataSize - m_nReadPos + m_nWritePos; 164 | copy_data_len = ready_data_len <= size ? ready_data_len : size; 165 | //sls_log(SLS_LOG_TRACE, "[%p]CSLSArray::get, read pos is before of the write pos, copy_data_len=%d, ready_data_len=%d, size=%d.", 166 | // this, copy_data_len, ready_data_len, size); 167 | if (m_nDataSize - m_nReadPos >= copy_data_len) { 168 | //no wrap round 169 | memcpy(data, m_arrayData + m_nReadPos, copy_data_len); 170 | m_nReadPos += copy_data_len; 171 | } else { 172 | memcpy(data, m_arrayData + m_nReadPos, m_nDataSize - m_nReadPos); 173 | //wrap around 174 | memcpy(data + (m_nDataSize - m_nReadPos), m_arrayData, copy_data_len - (m_nDataSize - m_nReadPos)); 175 | m_nReadPos = copy_data_len - (m_nDataSize - m_nReadPos); 176 | } 177 | m_nDataCount -= copy_data_len; 178 | } 179 | if (m_nReadPos == m_nDataSize) 180 | m_nReadPos = 0; 181 | 182 | if (m_nReadPos > m_nDataSize) { 183 | sls_log(SLS_LOG_WARNING, "[%p]CSLSArray::get, m_nReadPos=%d, but m_nDataSize=%d.", 184 | this, m_nReadPos, m_nDataSize); 185 | m_nReadPos = 0; 186 | } 187 | sls_log(SLS_LOG_TRACE, "[%p]CSLSArray::get, copy_data_lens=%d.", 188 | this, copy_data_len); 189 | return copy_data_len; 190 | } 191 | 192 | 193 | 194 | -------------------------------------------------------------------------------- /slscore/SLSArray.hpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #ifndef _SLSArray_INCLUDE_ 27 | #define _SLSArray_INCLUDE_ 28 | 29 | #include 30 | #include 31 | 32 | #include "common.hpp" 33 | #include "SLSLock.hpp" 34 | 35 | /** 36 | * CSLSArray 37 | */ 38 | class CSLSArray 39 | { 40 | public : 41 | CSLSArray(); 42 | ~CSLSArray(); 43 | 44 | public : 45 | int put(const uint8_t *data, int len); 46 | int get(uint8_t *data, int size); 47 | 48 | void setSize(int n); 49 | int count(); 50 | void clear(); 51 | private: 52 | uint8_t *m_arrayData; 53 | int m_nDataSize; 54 | int m_nDataCount; 55 | int m_nWritePos; 56 | int m_nReadPos; 57 | 58 | CSLSMutex m_mutex; 59 | 60 | int get_inline(uint8_t *data, int size); 61 | 62 | }; 63 | 64 | 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /slscore/SLSClient.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include "SLSClient.hpp" 35 | #include "SLSLog.hpp" 36 | 37 | /** 38 | * CSLSClient class implementation 39 | */ 40 | 41 | #define POLLING_TIME 1 /// Time in milliseconds between interrupt check 42 | 43 | 44 | CSLSClient::CSLSClient() 45 | { 46 | m_eid = 0; 47 | m_out_file = 0; 48 | m_data_count = 0; 49 | m_bit_rate = 0; 50 | 51 | m_ts_file_time_reader = NULL; 52 | m_invalid_begin_tm = sls_gettime_ms(); 53 | 54 | memset(m_url, 0, 1024); 55 | memset(m_ts_file_name, 0, 1024); 56 | memset(m_out_file_name, 0, 1024); 57 | 58 | sprintf(m_role_name, "client"); 59 | } 60 | 61 | CSLSClient::~CSLSClient() 62 | { 63 | } 64 | 65 | int CSLSClient::init_epoll() 66 | { 67 | int ret = 0; 68 | 69 | m_eid = CSLSSrt::libsrt_epoll_create(); 70 | if (m_eid < 0) { 71 | sls_log(SLS_LOG_INFO, "[%p]CSLSClient::work, srt_epoll_create failed.", this); 72 | return CSLSSrt::libsrt_neterrno(); 73 | } 74 | //compatible with srt v1.4.0 when container is empty. 75 | srt_epoll_set(m_eid, SRT_EPOLL_ENABLE_EMPTY); 76 | return ret; 77 | } 78 | 79 | int CSLSClient::uninit_epoll() 80 | { 81 | int ret = 0; 82 | if (m_eid >= 0) { 83 | CSLSSrt::libsrt_epoll_release(m_eid); 84 | sls_log(SLS_LOG_INFO, "[%p]CSLSEpollThread::work, srt_epoll_release ok.", this); 85 | } 86 | return ret; 87 | } 88 | 89 | 90 | int CSLSClient::play(const char* url, const char *out_file_name) 91 | { 92 | m_is_write = false; 93 | if (out_file_name != NULL && strlen(out_file_name) > 0) { 94 | strcpy(m_out_file_name, out_file_name); 95 | } 96 | 97 | return open_url(url); 98 | } 99 | 100 | int CSLSClient::open_url(const char* url) 101 | { 102 | // 103 | if (url == NULL || strlen(url) == 0) { 104 | sls_log(SLS_LOG_INFO, "[%p]CSLSClient::play, url='%s', must like 'srt://hostname:port?streamid=your_stream_id' or 'srt://hostname:port/app/stream_name'.", 105 | this, url?url:"null"); 106 | return SLS_ERROR; 107 | } 108 | 109 | int ret = open(url); 110 | if (SLS_OK != ret) { 111 | return ret; 112 | } 113 | 114 | //add to epoll 115 | ret = init_epoll(); 116 | if (SLS_OK != ret) { 117 | sls_log(SLS_LOG_INFO, "[%p]CSLSClient::play, init_epoll failed.", this); 118 | return CSLSSrt::libsrt_neterrno(); 119 | } 120 | ret = add_to_epoll(m_eid); 121 | if (SLS_OK != ret) { 122 | sls_log(SLS_LOG_INFO, "[%p]CSLSClient::play, add_to_epoll failed.", this); 123 | return CSLSSrt::libsrt_neterrno(); 124 | } 125 | return ret; 126 | } 127 | 128 | int CSLSClient::push(const char* url, const char *ts_file_name, bool loop) 129 | { 130 | if (NULL == ts_file_name || strlen(ts_file_name) == 0) { 131 | sls_log(SLS_LOG_INFO, "[%p]CSLSClient::push, failed, wrong ts_file_name='%s'.", 132 | this, ts_file_name); 133 | return SLS_ERROR; 134 | } 135 | if (NULL == m_ts_file_time_reader) { 136 | m_ts_file_time_reader = new CTSFileTimeReader; 137 | } 138 | int ret = m_ts_file_time_reader->open(ts_file_name, loop); 139 | if (SLS_OK != ret) { 140 | sls_log(SLS_LOG_INFO, "[%p]CSLSClient::push, m_ts_file_time_reader->open failed, ts_file_name='%s'.", 141 | this, ts_file_name); 142 | return SLS_ERROR; 143 | } 144 | 145 | m_is_write = true; 146 | return open_url(url); 147 | } 148 | 149 | int CSLSClient::close() 150 | { 151 | 152 | int ret = SLS_OK; 153 | if (0 != m_out_file) { 154 | ::close(m_out_file); 155 | m_out_file = 0; 156 | } 157 | if (0 != m_eid) { 158 | sls_log(SLS_LOG_INFO, "[%p]CSLSClient::close, ok, url='%s'.", this, m_url); 159 | remove_from_epoll(); 160 | uninit_epoll(); 161 | m_eid = 0; 162 | } 163 | if (NULL != m_ts_file_time_reader) { 164 | delete m_ts_file_time_reader ; 165 | m_ts_file_time_reader = NULL; 166 | } 167 | return CSLSRelay::close(); 168 | } 169 | 170 | int CSLSClient::handler() 171 | { 172 | if (m_is_write) { 173 | return write_data_handler(); 174 | } 175 | return read_data_handler(); 176 | } 177 | int CSLSClient::write_data_handler() 178 | { 179 | uint8_t szData[TS_UDP_LEN]; 180 | SRTSOCKET read_socks[1]; 181 | SRTSOCKET write_socks[1]; 182 | int read_len = 0; 183 | int write_len = 1; 184 | int64_t tm_ms; 185 | bool jitter = false; 186 | 187 | if (NULL == m_srt) { 188 | sls_log(SLS_LOG_ERROR, "[%p]CSLSClient::write_data_handler, failed, m_srt is null.", this); 189 | return SLS_ERROR; 190 | } 191 | if (0 == m_eid) { 192 | sls_log(SLS_LOG_ERROR, "[%p]CSLSClient::write_data_handler, failed, m_eid = 0.", this); 193 | return SLS_ERROR; 194 | } 195 | //check epoll 196 | int ret = srt_epoll_wait(m_eid, read_socks, &read_len, write_socks, &write_len, POLLING_TIME, 0, 0, 0, 0); 197 | if (0 > ret) { 198 | return SLS_OK; 199 | } 200 | if (0 >= write_socks[0]) { 201 | return SLS_OK; 202 | } 203 | 204 | ret = m_ts_file_time_reader->get(szData, TS_UDP_LEN, tm_ms, jitter); 205 | if (SLS_OK != ret) { 206 | return SLS_ERROR; 207 | } 208 | //write data 209 | int n = m_srt->libsrt_write((char *)szData, TS_UDP_LEN); 210 | if (n <= 0) { 211 | sls_log(SLS_LOG_TRACE, "[%p]CSLSClient::write_data_handler, libsrt_read failure, n=%d.", this, n, TS_UDP_LEN); 212 | int state = get_state(); 213 | if (SLS_RS_INVALID == state || SLS_RS_UNINIT == state) 214 | { 215 | return SLS_ERROR; 216 | } 217 | } 218 | m_sync_clock.wait(tm_ms); 219 | 220 | m_data_count += n; 221 | int64_t cur_tm = sls_gettime_ms(); 222 | int d = cur_tm - m_invalid_begin_tm; 223 | if (d >= 500) { 224 | m_bit_rate = m_data_count*8/d; 225 | m_data_count = 0; 226 | m_invalid_begin_tm = sls_gettime_ms(); 227 | } 228 | return n; 229 | } 230 | 231 | int CSLSClient::read_data_handler() 232 | { 233 | char szData[TS_UDP_LEN]; 234 | SRTSOCKET read_socks[1]; 235 | SRTSOCKET write_socks[1]; 236 | int read_len = 0; 237 | int write_len = 0; 238 | 239 | if (m_is_write) { 240 | //push 241 | return SLS_OK; 242 | } else { 243 | //play 244 | if (NULL == m_srt) { 245 | sls_log(SLS_LOG_ERROR, "[%p]CSLSClient::read_data_handler, failed, m_srt is null.", this); 246 | return SLS_ERROR; 247 | } 248 | if (0 == m_eid) { 249 | sls_log(SLS_LOG_ERROR, "[%p]CSLSClient::read_data_handler, failed, m_eid = 0.", this); 250 | return SLS_ERROR; 251 | } 252 | read_len = 1; 253 | //check epoll 254 | int ret = srt_epoll_wait(m_eid, read_socks, &read_len, write_socks, &write_len, POLLING_TIME, 0, 0, 0, 0); 255 | if (0 > ret) { 256 | return SLS_OK; 257 | } 258 | if (0 >= read_socks[0]) { 259 | return SLS_OK; 260 | } 261 | 262 | //read data 263 | int n = m_srt->libsrt_read(szData, TS_UDP_LEN); 264 | if (n <= 0) { 265 | sls_log(SLS_LOG_ERROR, "[%p]CSLSClient::read_data_handler, libsrt_read failure, n=%d.", this, n, TS_UDP_LEN); 266 | return SLS_OK; 267 | } 268 | 269 | //update invalid begin time 270 | //m_invalid_begin_tm = sls_gettime(); 271 | 272 | if (0 == m_out_file) { 273 | if (strlen(m_out_file_name) > 0) { 274 | m_out_file = ::open(m_out_file_name, O_WRONLY|O_CREAT, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IXOTH); 275 | if (0 == m_out_file) { 276 | sls_log(SLS_LOG_ERROR, "[%p]CSLSClient::read_data_handler, open file='%s' failed, '%s'.\n", m_out_file_name, strerror(errno)); 277 | return SLS_ERROR; 278 | } 279 | } 280 | } 281 | if (0 != m_out_file) { 282 | ::write(m_out_file, szData, TS_UDP_LEN); 283 | } 284 | m_data_count += n; 285 | int64_t cur_tm = sls_gettime_ms(); 286 | int d = cur_tm - m_invalid_begin_tm; 287 | if (d >= 500) { 288 | m_bit_rate = m_data_count*8/d; 289 | m_data_count = 0; 290 | m_invalid_begin_tm = sls_gettime_ms(); 291 | } 292 | 293 | if (n != TS_UDP_LEN) { 294 | sls_log(SLS_LOG_INFO, "[%p]CSLSClient::read_data_handler, libsrt_read n=%d, expect %d.", this, n, TS_UDP_LEN); 295 | } 296 | return n; 297 | } 298 | } 299 | 300 | int64_t CSLSClient::get_bitrate() 301 | { 302 | return m_bit_rate; 303 | } 304 | 305 | 306 | 307 | -------------------------------------------------------------------------------- /slscore/SLSClient.hpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #ifndef _SLSClient_INCLUDE_ 27 | #define _SLSClient_INCLUDE_ 28 | 29 | #include 30 | 31 | #include "SLSRelay.hpp" 32 | #include "TSFileTimeReader.hpp" 33 | 34 | 35 | /** 36 | * CSLSClient 37 | */ 38 | class CSLSClient: public CSLSRelay 39 | { 40 | public : 41 | CSLSClient(); 42 | virtual ~CSLSClient(); 43 | 44 | int play(const char *url, const char *out_file_name); 45 | int push(const char *url, const char *ts_file_name, bool loop); 46 | 47 | virtual int close(); 48 | virtual int handler(); 49 | 50 | int64_t get_bitrate(); 51 | 52 | protected: 53 | int init_epoll(); 54 | int uninit_epoll(); 55 | 56 | int open_url(const char* url); 57 | int write_data_handler(); 58 | int read_data_handler(); 59 | 60 | 61 | char m_url[1024]; 62 | char m_ts_file_name[1024]; 63 | char m_out_file_name[1024]; 64 | 65 | int m_eid; 66 | int m_out_file; 67 | 68 | int64_t m_data_count; 69 | int64_t m_bit_rate;//kbit/s 70 | 71 | CTSFileTimeReader *m_ts_file_time_reader; 72 | CSLSSyncClock m_sync_clock; 73 | 74 | }; 75 | 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /slscore/SLSEpollThread.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #include 27 | #include 28 | 29 | 30 | #include "SLSEpollThread.hpp" 31 | #include "SLSLog.hpp" 32 | #include "common.hpp" 33 | #include "SLSRole.hpp" 34 | 35 | #include 36 | 37 | /** 38 | * CSLSThread class implementation 39 | */ 40 | 41 | CSLSEpollThread::CSLSEpollThread() 42 | { 43 | } 44 | 45 | CSLSEpollThread::~CSLSEpollThread() 46 | { 47 | 48 | } 49 | 50 | int CSLSEpollThread::init_epoll() 51 | { 52 | int ret = 0; 53 | 54 | m_eid = CSLSSrt::libsrt_epoll_create(); 55 | if (m_eid < 0) { 56 | sls_log(SLS_LOG_INFO, "[%p]CSLSEpollThread::work, srt_epoll_create failed. th_id=%lld.", this, m_th_id); 57 | return CSLSSrt::libsrt_neterrno(); 58 | } 59 | //compatible with srt v1.4.0 when container is empty. 60 | srt_epoll_set(m_eid, SRT_EPOLL_ENABLE_EMPTY); 61 | return ret; 62 | } 63 | 64 | int CSLSEpollThread::uninit_epoll() 65 | { 66 | int ret = 0; 67 | if (m_eid >= 0) { 68 | CSLSSrt::libsrt_epoll_release(m_eid); 69 | sls_log(SLS_LOG_INFO, "[%p]CSLSEpollThread::work, srt_epoll_release ok, m_th_id=%lld.", this, m_th_id); 70 | } 71 | return ret; 72 | } 73 | 74 | int CSLSEpollThread::work() 75 | { 76 | int ret = 0; 77 | sls_log(SLS_LOG_INFO, "[%p]CSLSEpollThread::work, begin th_id=%lld.", this, m_th_id); 78 | //epoll loop 79 | while (!m_exit) { 80 | handler(); 81 | } 82 | 83 | clear(); 84 | sls_log(SLS_LOG_INFO, "[%p]CSLSEpollThread::work, end th_id=%lld.", this, m_th_id); 85 | return ret; 86 | } 87 | 88 | int CSLSEpollThread::handler() 89 | { 90 | int ret = 0; 91 | 92 | return ret; 93 | } 94 | 95 | -------------------------------------------------------------------------------- /slscore/SLSEpollThread.hpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #ifndef _SLSEpollThread_INCLUDE_ 27 | #define _SLSEpollThread_INCLUDE_ 28 | 29 | #include 30 | #include "SLSThread.hpp" 31 | 32 | #define MAX_SOCK_COUNT 1024 33 | 34 | /** 35 | * CSLSEpollThread , the base thread class 36 | */ 37 | class CSLSEpollThread: public CSLSThread 38 | { 39 | public : 40 | CSLSEpollThread(); 41 | ~CSLSEpollThread(); 42 | 43 | virtual int work(); 44 | 45 | int init_epoll(); 46 | int uninit_epoll(); 47 | 48 | protected: 49 | virtual int handler(); 50 | 51 | int add_to_epoll(int fd, bool write) ; 52 | 53 | int m_eid; 54 | SRTSOCKET m_read_socks[MAX_SOCK_COUNT]; 55 | SRTSOCKET m_write_socks[MAX_SOCK_COUNT]; 56 | 57 | }; 58 | 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /slscore/SLSGroup.hpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #ifndef _SLSGroup_INCLUDE_ 27 | #define _SLSGroup_INCLUDE_ 28 | 29 | #include 30 | 31 | #include "SLSEpollThread.hpp" 32 | #include "SLSRoleList.hpp" 33 | #include "SLSRole.hpp" 34 | #include "SLSMapRelay.hpp" 35 | #include "HttpClient.hpp" 36 | 37 | /** 38 | * CSLSGroup , group of players, publishers and listener 39 | */ 40 | class CSLSGroup : public CSLSEpollThread 41 | { 42 | public : 43 | CSLSGroup(); 44 | ~CSLSGroup(); 45 | 46 | int start(); 47 | int stop(); 48 | void reload(); 49 | 50 | void set_role_list(CSLSRoleList *list_role); 51 | void set_worker_connections(int n); 52 | void set_worker_number(int n); 53 | 54 | virtual int handler(); 55 | 56 | void set_stat_post_interval(int interval); 57 | void set_http_stat_post(CHttpClient *p); 58 | 59 | void get_stat_info(std::string &info); 60 | 61 | protected: 62 | virtual void clear(); 63 | 64 | private: 65 | CSLSRoleList *m_list_role; 66 | std::list m_list_wait_http_role; 67 | std::map m_map_role; 68 | std::list m_list_reconnect_relay_manager; 69 | 70 | 71 | void idle_check(); 72 | void check_reconnect_relay(); 73 | void check_invalid_sock(); 74 | void check_new_role(); 75 | void check_wait_http_role(); 76 | 77 | int m_worker_connections; 78 | int m_worker_number; 79 | int64_t m_cur_time_microsec; 80 | bool m_reload; 81 | 82 | int64_t m_stat_post_last_tm_ms; 83 | int m_stat_post_interval; 84 | CSLSMutex m_mutex_stat; 85 | std::string m_stat_info; 86 | 87 | }; 88 | 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /slscore/SLSListener.hpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #ifndef _SLSListener_INCLUDE_ 27 | #define _SLSListener_INCLUDE_ 28 | 29 | #include 30 | #include 31 | 32 | #include "SLSRole.hpp" 33 | #include "SLSRoleList.hpp" 34 | #include "SLSPublisher.hpp" 35 | #include "conf.hpp" 36 | #include "SLSRecycleArray.hpp" 37 | #include "SLSMapPublisher.hpp" 38 | #include "SLSMapRelay.hpp" 39 | 40 | /** 41 | * server conf 42 | */ 43 | SLS_CONF_DYNAMIC_DECLARE_BEGIN(server) 44 | char domain_player[URL_MAX_LEN]; 45 | char domain_publisher[URL_MAX_LEN]; 46 | int listen; 47 | int backlog; 48 | int latency; 49 | int idle_streams_timeout;//unit s; -1: unlimited 50 | char on_event_url[URL_MAX_LEN]; 51 | char default_sid[STR_MAX_LEN]; 52 | SLS_CONF_DYNAMIC_DECLARE_END 53 | 54 | /** 55 | * sls_conf_server_t 56 | */ 57 | SLS_CONF_CMD_DYNAMIC_DECLARE_BEGIN(server) 58 | SLS_SET_CONF(server, string, domain_player, "play domain", 1, URL_MAX_LEN-1), 59 | SLS_SET_CONF(server, string, domain_publisher, "", 1, URL_MAX_LEN-1), 60 | SLS_SET_CONF(server, int, listen, "listen port", 1, 65535), 61 | SLS_SET_CONF(server, int, backlog, "how many sockets may be allowed to wait until they are accepted", 1, 1024), 62 | SLS_SET_CONF(server, int, latency, "latency.", 1, 5000), 63 | SLS_SET_CONF(server, int, idle_streams_timeout, "players idle timeout when no publisher" , -1, 86400), 64 | SLS_SET_CONF(server, string, on_event_url, "on connect/close http url", 1, URL_MAX_LEN-1), 65 | SLS_SET_CONF(server, string, default_sid, "default sid to use when no streamid is given", 1, STR_MAX_LEN-1), 66 | SLS_CONF_CMD_DYNAMIC_DECLARE_END 67 | 68 | 69 | /** 70 | * SLSListener 71 | */ 72 | class CSLSListener : public CSLSRole 73 | { 74 | public : 75 | CSLSListener(); 76 | ~CSLSListener(); 77 | 78 | int init(); 79 | int uninit(); 80 | 81 | 82 | virtual int start(); 83 | virtual int stop(); 84 | 85 | virtual int handler(); 86 | 87 | void set_role_list(CSLSRoleList *list_role); 88 | void set_map_publisher(CSLSMapPublisher * publisher); 89 | void set_map_puller(CSLSMapRelay *map_puller); 90 | void set_map_pusher(CSLSMapRelay *map_puller); 91 | void set_record_hls_path_prefix(char *path); 92 | 93 | virtual std::string get_stat_info(); 94 | 95 | private: 96 | CSLSRoleList * m_list_role; 97 | CSLSMapPublisher * m_map_publisher; 98 | CSLSMapRelay * m_map_puller; 99 | CSLSMapRelay * m_map_pusher; 100 | 101 | CSLSMutex m_mutex; 102 | 103 | int m_idle_streams_timeout_role; 104 | std::string m_stat_info; 105 | char m_default_sid[1024]; 106 | char m_http_url_role[URL_MAX_LEN]; 107 | char m_record_hls_path_prefix[URL_MAX_LEN]; 108 | 109 | int init_conf_app(); 110 | 111 | 112 | }; 113 | 114 | 115 | #endif 116 | -------------------------------------------------------------------------------- /slscore/SLSLock.hpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #ifndef _SLSLock_INCLUDE_ 27 | #define _SLSLock_INCLUDE_ 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | 34 | /** 35 | * CSLSMutex 36 | */ 37 | 38 | class CSLSMutex 39 | { 40 | public : 41 | CSLSMutex() 42 | { 43 | pthread_mutex_init(&m_mutex, NULL); 44 | } 45 | ~CSLSMutex() 46 | { 47 | pthread_mutex_destroy(&m_mutex); 48 | } 49 | pthread_mutex_t * get_mutex() { return &m_mutex; } 50 | private: 51 | pthread_mutex_t m_mutex; 52 | 53 | }; 54 | 55 | class CSLSRWLock 56 | { 57 | public: 58 | CSLSRWLock() 59 | { 60 | m_inited = false; 61 | int ret = pthread_rwlock_init(&m_rwlock, NULL); 62 | if (0 == ret) { 63 | m_inited = true; 64 | } else { 65 | printf("pthread_rwlock_init faild, ret=%d.", ret);; 66 | } 67 | } 68 | ~CSLSRWLock() 69 | { 70 | if (m_inited) { 71 | int ret = pthread_rwlock_destroy(&m_rwlock); 72 | if (0 != ret) 73 | { 74 | printf("pthread_rwlock_destroy faild, ret=%d.", ret);; 75 | } 76 | } 77 | } 78 | 79 | int try_lock_write() 80 | { 81 | return pthread_rwlock_trywrlock(&m_rwlock); 82 | } 83 | int try_lock_read() 84 | { 85 | return pthread_rwlock_tryrdlock(&m_rwlock); 86 | } 87 | int lock_write() 88 | { 89 | return pthread_rwlock_wrlock(&m_rwlock); 90 | } 91 | int lock_read() 92 | { 93 | return pthread_rwlock_rdlock(&m_rwlock); 94 | } 95 | int unlock() 96 | { 97 | return pthread_rwlock_unlock(&m_rwlock); 98 | } 99 | private: 100 | pthread_rwlock_t m_rwlock; 101 | bool m_inited; 102 | }; 103 | 104 | /** 105 | * CSLSLock 106 | */ 107 | class CSLSLock 108 | { 109 | public : 110 | CSLSLock(CSLSRWLock * clock, int write) 111 | { 112 | m_mutex = NULL; 113 | m_clock = NULL; 114 | m_locked =false; 115 | if (NULL == clock) 116 | return ; 117 | int ret = 0; 118 | if (write) { 119 | ret = clock->lock_write(); 120 | } else { 121 | ret = clock->lock_read(); 122 | } 123 | if (0 != ret) { 124 | printf("SLS Error: clock failure, ret=%d.\n", ret); 125 | } else { 126 | m_clock = clock; 127 | m_locked =true; 128 | } 129 | } 130 | 131 | CSLSLock(CSLSMutex * m) 132 | { 133 | m_clock = NULL; 134 | m_mutex = NULL; 135 | m_locked =false; 136 | if (m) { 137 | m_mutex = m->get_mutex(); 138 | int ret = pthread_mutex_lock(m_mutex); 139 | if (0 == ret) { 140 | m_locked = true; 141 | } else { 142 | printf("SLS Error: pthread_mutex_lock failure, ret=%d.\n", ret); 143 | } 144 | } 145 | 146 | } 147 | 148 | ~CSLSLock() 149 | { 150 | if (m_locked && m_mutex) 151 | pthread_mutex_unlock(m_mutex); 152 | if (m_locked && m_clock) 153 | m_clock->unlock(); 154 | } 155 | private: 156 | 157 | pthread_mutex_t * m_mutex; 158 | CSLSRWLock * m_clock; 159 | 160 | bool m_locked; 161 | 162 | }; 163 | 164 | 165 | 166 | 167 | 168 | #endif 169 | -------------------------------------------------------------------------------- /slscore/SLSLog.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "SLSLog.hpp" 32 | #include "SLSLock.hpp" 33 | 34 | CSLSLog* CSLSLog::m_pInstance = NULL; 35 | 36 | CSLSLog::CSLSLog() 37 | { 38 | m_level = SLS_LOG_INFO; 39 | m_log_file = NULL; 40 | sprintf(log_filename, ""); 41 | } 42 | CSLSLog::~CSLSLog() 43 | { 44 | 45 | } 46 | int CSLSLog::create_instance() 47 | { 48 | if (!m_pInstance) { 49 | m_pInstance = new CSLSLog(); 50 | m_pInstance->m_level = SLS_LOG_ERROR;//default 51 | return 0; 52 | } 53 | return -1; 54 | } 55 | int CSLSLog::destory_instance() 56 | { 57 | SAFE_DELETE(m_pInstance); 58 | return 0; 59 | } 60 | 61 | void CSLSLog::log(int level, const char *fmt, ...) 62 | { 63 | if (!m_pInstance) 64 | m_pInstance = new CSLSLog(); 65 | if (level > m_pInstance->m_level) 66 | return; 67 | 68 | va_list vl; 69 | va_start(vl, fmt); 70 | m_pInstance->print_log(level, fmt, vl); 71 | va_end (vl); 72 | } 73 | 74 | 75 | void CSLSLog::print_log(int level, const char *fmt, va_list vl) 76 | { 77 | CSLSLock lock(&m_mutex); 78 | char buf[4096] = {0}; 79 | char buf_info[4096] = {0}; 80 | char cur_time[STR_DATE_TIME_LEN] = {0}; 81 | int64_t cur_time_msec = sls_gettime_ms(); 82 | int64_t cur_time_sec = cur_time_msec/1000; 83 | cur_time_msec = cur_time_msec - cur_time_sec*1000; 84 | sls_gettime_fmt(cur_time, cur_time_sec, "%Y-%m-%d %H:%M:%S"); 85 | vsnprintf (buf , 4095 , fmt , vl); 86 | //sprintf(buf_info, "%s %s: %s\n" , cur_time, LOG_LEVEL_NAME[level], buf); 87 | sprintf(buf_info, "%s:%03d %s %s: %s\n" , cur_time, cur_time_msec, APP_NAME, LOG_LEVEL_NAME[level], buf); 88 | printf(buf_info); 89 | 90 | if (m_log_file) { 91 | fwrite(buf_info, strlen(buf_info), 1, m_log_file); 92 | } 93 | } 94 | 95 | void CSLSLog::set_log_level(char * level) 96 | { 97 | if (!m_pInstance) 98 | m_pInstance = new CSLSLog(); 99 | 100 | level = sls_strupper(level);//to upper 101 | int n = sizeof(LOG_LEVEL_NAME)/sizeof(char*); 102 | for (int i = 0; i < n; i ++) { 103 | if (strcmp(level, LOG_LEVEL_NAME[i]) == 0) { 104 | m_pInstance->m_level = i; 105 | printf("set log level='%s'.\n" , level, LOG_LEVEL_NAME[i]); 106 | return ; 107 | } 108 | } 109 | printf("!!!wrong log level '%s', set default '%s'.\n" , level, LOG_LEVEL_NAME[m_pInstance->m_level]); 110 | } 111 | 112 | void CSLSLog::set_log_file(char * file_name) 113 | { 114 | if (!m_pInstance) 115 | m_pInstance = new CSLSLog(); 116 | 117 | if (strlen(m_pInstance->log_filename) == 0) { 118 | sprintf(m_pInstance->log_filename, "%s", file_name); 119 | m_pInstance->m_log_file = fopen(m_pInstance->log_filename, "a"); 120 | } 121 | 122 | 123 | } 124 | 125 | -------------------------------------------------------------------------------- /slscore/SLSLog.hpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #ifndef _SLSLOG_INCLUDE_ 27 | #define _SLSLOG_INCLUDE_ 28 | 29 | #include 30 | #include 31 | 32 | #include "common.hpp" 33 | #include "SLSLock.hpp" 34 | 35 | #define SLS_LOG_FATAL 0 36 | #define SLS_LOG_ERROR 1 37 | #define SLS_LOG_WARNING 2 38 | #define SLS_LOG_INFO 3 39 | #define SLS_LOG_DEBUG 4 40 | #define SLS_LOG_TRACE 5 41 | static char const * LOG_LEVEL_NAME[] = { 42 | "FATAL", 43 | "ERROR", 44 | "WARNING", 45 | "INFO", 46 | "DEBUG", 47 | "TRACE" 48 | }; 49 | 50 | 51 | static const char APP_NAME[] = "SLS"; 52 | 53 | #define sls_log CSLSLog::log 54 | #define sls_set_log_level CSLSLog::set_log_level 55 | #define sls_set_log_file CSLSLog::set_log_file 56 | /** 57 | * CSLSLog 58 | */ 59 | class CSLSLog 60 | { 61 | private : 62 | CSLSLog(); 63 | ~CSLSLog(); 64 | 65 | public : 66 | static int create_instance(); 67 | static int destory_instance(); 68 | static void log(int level, const char *fmt, ...); 69 | static void set_log_level(char *level); 70 | static void set_log_file(char * file_name); 71 | 72 | private: 73 | static CSLSLog* m_pInstance; 74 | int m_level; 75 | CSLSMutex m_mutex; 76 | char log_filename[1024]; 77 | FILE * m_log_file; 78 | 79 | void print_log(int level, const char *fmt, va_list vl); 80 | }; 81 | 82 | 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /slscore/SLSManager.hpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #ifndef _SLSManager_INCLUDE_ 27 | #define _SLSManager_INCLUDE_ 28 | 29 | #include 30 | 31 | #include "SLSRole.hpp" 32 | #include "SLSRoleList.hpp" 33 | #include "SLSGroup.hpp" 34 | #include "SLSListener.hpp" 35 | #include "conf.hpp" 36 | #include "SLSMapData.hpp" 37 | #include "SLSMapRelay.hpp" 38 | 39 | #include "json.hpp" 40 | using json = nlohmann::json; 41 | 42 | /** 43 | * srt conf declare 44 | */ 45 | SLS_CONF_DYNAMIC_DECLARE_BEGIN(srt) 46 | char log_file[URL_MAX_LEN]; 47 | char log_level[URL_MAX_LEN]; 48 | int worker_threads; 49 | int worker_connections; 50 | char stat_post_url[URL_MAX_LEN]; 51 | int stat_post_interval; 52 | char record_hls_path_prefix[URL_MAX_LEN]; 53 | int http_port; 54 | char cors_header[URL_MAX_LEN]; 55 | SLS_CONF_DYNAMIC_DECLARE_END 56 | 57 | 58 | /** 59 | * srt cmd declare 60 | */ 61 | SLS_CONF_CMD_DYNAMIC_DECLARE_BEGIN(srt) 62 | SLS_SET_CONF(srt, string, log_file, "save log file name.", 1, URL_MAX_LEN-1), 63 | SLS_SET_CONF(srt, string, log_level, "log level", 1, URL_MAX_LEN-1), 64 | SLS_SET_CONF(srt, int, worker_threads, "count of worker thread, if 0, only main thread.", 0, 100), 65 | SLS_SET_CONF(srt, int, worker_connections, "", 1, 1024), 66 | SLS_SET_CONF(srt, string, stat_post_url, "statistic info post url", 1, URL_MAX_LEN-1), 67 | SLS_SET_CONF(srt, int, stat_post_interval, "interval of statistic info post.", 1, 60), 68 | SLS_SET_CONF(srt, string, record_hls_path_prefix, "hls path prefix", 1, URL_MAX_LEN-1), 69 | SLS_SET_CONF(srt, int, http_port, "rest api port", 1, 65535), 70 | SLS_SET_CONF(srt, string, cors_header, "cors header", 1, URL_MAX_LEN-1) 71 | SLS_CONF_CMD_DYNAMIC_DECLARE_END 72 | 73 | 74 | /** 75 | * CSLSManager , manage players, publishers and listener 76 | */ 77 | class CSLSManager 78 | { 79 | public : 80 | CSLSManager(); 81 | virtual ~CSLSManager(); 82 | 83 | 84 | int start(); 85 | int stop(); 86 | int reload(); 87 | int single_thread_handler(); 88 | json generate_json_for_all_publishers(int clear); 89 | json generate_json_for_publisher(std::string publisherName, int clear); 90 | json create_json_stats_for_publisher(CSLSRole *role, int clear); 91 | int check_invalid(); 92 | bool is_single_thread(); 93 | 94 | void get_stat_info(std::string &info); 95 | static int stat_client_callback(void *p, HTTP_CALLBACK_TYPE type, void *v, void* context); 96 | 97 | private: 98 | std::list m_servers; 99 | int m_server_count; 100 | CSLSMapData *m_map_data; 101 | CSLSMapPublisher *m_map_publisher; 102 | CSLSMapRelay *m_map_puller; 103 | CSLSMapRelay *m_map_pusher; 104 | 105 | std::list m_workers; 106 | int m_worker_threads; 107 | 108 | CSLSRoleList * m_list_role; 109 | CSLSGroup * m_single_group; 110 | }; 111 | 112 | 113 | #endif 114 | -------------------------------------------------------------------------------- /slscore/SLSMapData.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include "SLSMapData.hpp" 31 | #include "SLSLog.hpp" 32 | 33 | 34 | /** 35 | * CSLSMapData class implementation 36 | */ 37 | 38 | CSLSMapData::CSLSMapData() 39 | { 40 | } 41 | CSLSMapData::~CSLSMapData() 42 | { 43 | clear(); 44 | } 45 | 46 | int CSLSMapData::add(char *key) 47 | { 48 | int ret = SLS_OK; 49 | std::string strKey = std::string(key); 50 | 51 | CSLSLock lock(&m_rwclock, true); 52 | 53 | std::map::iterator item; 54 | item = m_map_array.find(strKey); 55 | if (item != m_map_array.end()) { 56 | CSLSRecycleArray * array_data = item->second; 57 | if (array_data) { 58 | sls_log(SLS_LOG_INFO, "[%p]CSLSMapData::add, failed, key=%s, array_data=%p, exist.", 59 | this, key, array_data); 60 | return ret; 61 | } 62 | //m_map_array.erase(item); 63 | } 64 | 65 | CSLSRecycleArray * data_array = new CSLSRecycleArray; 66 | //m_map_array.insert(make_pair(strKey, data_array)); 67 | m_map_array[strKey] = data_array; 68 | sls_log(SLS_LOG_INFO, "[%p]CSLSMapData::add ok, key='%s'.", 69 | this, key); 70 | return ret; 71 | } 72 | 73 | int CSLSMapData::remove(char *key) 74 | { 75 | int ret = SLS_ERROR; 76 | std::string strKey = std::string(key); 77 | 78 | CSLSLock lock(&m_rwclock, true); 79 | 80 | std::map::iterator item_ti; 81 | item_ti = m_map_ts_info.find(strKey); 82 | if (item_ti != m_map_ts_info.end()) { 83 | ts_info *ti = item_ti->second; 84 | if (ti) { 85 | delete ti; 86 | } 87 | m_map_ts_info.erase(item_ti); 88 | } 89 | 90 | std::map::iterator item; 91 | item = m_map_array.find(strKey); 92 | if (item != m_map_array.end()) { 93 | CSLSRecycleArray * array_data = item->second; 94 | sls_log(SLS_LOG_INFO, "[%p]CSLSMapData::remove, key='%s' delete array_data=%p.", 95 | this, key, array_data); 96 | if (array_data) { 97 | delete array_data; 98 | } 99 | m_map_array.erase(item); 100 | return SLS_OK; 101 | } 102 | return ret; 103 | } 104 | 105 | bool CSLSMapData::is_exist(char *key) 106 | { 107 | 108 | CSLSLock lock(&m_rwclock, true); 109 | std::string strKey = std::string(key); 110 | 111 | std::map::iterator item; 112 | item = m_map_array.find(key); 113 | if (item != m_map_array.end()) { 114 | CSLSRecycleArray * array_data = item->second; 115 | if (array_data) { 116 | sls_log(SLS_LOG_TRACE, "[%p]CSLSMapData::is_exist, key=%s, exist.", 117 | this, key); 118 | return true; 119 | } else { 120 | sls_log(SLS_LOG_TRACE, "[%p]CSLSMapData::is_exist, is_exist, key=%s, data_array is null.", 121 | this, key); 122 | } 123 | } else { 124 | sls_log(SLS_LOG_TRACE, "[%p]CSLSMapData::add, is_exist, key=%s, not exist.", 125 | this, key); 126 | } 127 | return false; 128 | } 129 | 130 | 131 | int CSLSMapData::put(char *key, char *data, int len, int64_t *last_read_time) 132 | { 133 | int ret = SLS_OK; 134 | 135 | CSLSLock lock(&m_rwclock, true); 136 | std::string strKey = std::string(key); 137 | 138 | std::map::iterator item; 139 | item = m_map_array.find(strKey); 140 | if (item == m_map_array.end()) { 141 | sls_log(SLS_LOG_ERROR, "[%p]CSLSMapData::put, key=%s, not found data array.", 142 | this, key); 143 | return SLS_ERROR; 144 | } 145 | CSLSRecycleArray *array_data = item->second; 146 | if (NULL == array_data) { 147 | sls_log(SLS_LOG_ERROR, "[%p]CSLSMapData::get, key=%s, array_data is NULL.", 148 | this, key); 149 | } 150 | 151 | ret = array_data->put(data, len); 152 | if (ret != len) { 153 | sls_log(SLS_LOG_ERROR, "[%p]CSLSMapData::put, key=%s, array_data->put failed, len=%d, but ret=%d.", 154 | this, key, len, ret); 155 | } 156 | if (NULL != last_read_time) { 157 | *last_read_time = array_data->get_last_read_time(); 158 | } 159 | 160 | //check sps and pps 161 | ts_info *ti = NULL; 162 | std::map::iterator item_ti; 163 | item_ti = m_map_ts_info.find(strKey); 164 | if (item_ti == m_map_ts_info.end()) { 165 | ti = new ts_info; 166 | sls_init_ts_info(ti); 167 | ti->need_spspps = true; 168 | m_map_ts_info[strKey] = ti; 169 | }else{ 170 | ti = item_ti->second; 171 | } 172 | 173 | if (SLS_OK == check_ts_info(data, len, ti)) { 174 | sls_log(SLS_LOG_INFO, "[%p]CSLSMapData::put, check_spspps ok, key=%s.", 175 | this, key); 176 | } 177 | 178 | return ret; 179 | } 180 | 181 | int CSLSMapData::get(char *key, char *data, int len, SLSRecycleArrayID *read_id, int aligned) 182 | { 183 | int ret = SLS_OK; 184 | 185 | CSLSLock lock(&m_rwclock, false); 186 | std::string strKey = std::string(key); 187 | 188 | std::map::iterator item; 189 | item = m_map_array.find(strKey); 190 | if (item == m_map_array.end()) { 191 | sls_log(SLS_LOG_TRACE, "[%p]CSLSMapData::get, key=%s, not found data array,", 192 | this, key); 193 | return SLS_ERROR; 194 | } 195 | CSLSRecycleArray *array_data = item->second; 196 | if (NULL == array_data) { 197 | sls_log(SLS_LOG_WARNING, "[%p]CSLSMapData::get, key=%s, array_data is NULL.", 198 | this, key); 199 | return SLS_ERROR; 200 | } 201 | 202 | bool b_first = read_id->bFirst; 203 | ret = array_data->get(data, len, read_id, aligned); 204 | if (b_first) { 205 | //get sps and pps 206 | ret = get_ts_info(key, data, len); 207 | sls_log(SLS_LOG_INFO, "[%p]CSLSMapData::get, get sps pps ok, key=%s, len=%d.", 208 | this, key, ret); 209 | } 210 | return ret; 211 | } 212 | 213 | int CSLSMapData::get_ts_info(char *key, char *data, int len) 214 | { 215 | int ret = 0; 216 | ts_info *ti = NULL; 217 | std::string strKey = std::string(key); 218 | std::map::iterator item_ti; 219 | item_ti = m_map_ts_info.find(strKey); 220 | if (item_ti != m_map_ts_info.end()) { 221 | ti = item_ti->second; 222 | if (len >= TS_UDP_LEN) { 223 | memcpy(data, ti->ts_data, TS_UDP_LEN); 224 | ret = TS_UDP_LEN; 225 | } 226 | } 227 | return ret; 228 | } 229 | 230 | void CSLSMapData::clear() 231 | { 232 | CSLSLock lock(&m_rwclock, true); 233 | std::map::iterator it; 234 | for(it=m_map_array.begin(); it!=m_map_array.end(); ) { 235 | CSLSRecycleArray * array_data = it->second; 236 | if (array_data) { 237 | delete array_data; 238 | } 239 | it ++; 240 | } 241 | m_map_array.clear(); 242 | std::map::iterator item_ti; 243 | for(item_ti=m_map_ts_info.begin(); item_ti!=m_map_ts_info.end(); ) { 244 | ts_info *ti = item_ti->second; 245 | if (ti) { 246 | delete ti; 247 | } 248 | item_ti ++; 249 | } 250 | m_map_ts_info.clear(); 251 | } 252 | 253 | int CSLSMapData::check_ts_info(char *data, int len, ts_info *ti) 254 | { 255 | //only get the first, suppose the sps and pps are not changed always. 256 | for (int i = 0; i < len;) { 257 | if (ti->sps_len > 0 && ti->pps_len > 0 && ti->pat_len > 0 && ti->pat_len > 0) { 258 | break; 259 | } 260 | sls_parse_ts_info((const uint8_t *)data + i, ti); 261 | i += TS_PACK_LEN; 262 | } 263 | 264 | return SLS_ERROR; 265 | } 266 | 267 | 268 | -------------------------------------------------------------------------------- /slscore/SLSMapData.hpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #ifndef _SLSMapData_INCLUDE_ 27 | #define _SLSMapData_INCLUDE_ 28 | 29 | #include 30 | #include 31 | 32 | #include "SLSRecycleArray.hpp" 33 | #include "SLSLock.hpp" 34 | 35 | class CSLSMapData 36 | { 37 | public: 38 | CSLSMapData(); 39 | virtual ~CSLSMapData(); 40 | 41 | int add(char *key); 42 | int remove(char *key); 43 | void clear(); 44 | 45 | int put(char *key, char *data, int len, int64_t *last_read_time=NULL); 46 | int get(char *key, char *data, int len, SLSRecycleArrayID *read_id, int aligned=0); 47 | 48 | bool is_exist(char *key); 49 | 50 | int get_ts_info(char *key, char *data, int len); 51 | private: 52 | std::map m_map_array; //uplive_key_stream:data' 53 | std::map m_map_ts_info; //uplive_key_stream:ts_info' 54 | CSLSRWLock m_rwclock; 55 | 56 | int check_ts_info(char *data, int len, ts_info *ti); 57 | }; 58 | 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /slscore/SLSMapPublisher.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #include 27 | #include 28 | 29 | 30 | #include "SLSMapPublisher.hpp" 31 | #include "SLSLog.hpp" 32 | 33 | 34 | /** 35 | * CSLSMapPublisher class implementation 36 | */ 37 | 38 | CSLSMapPublisher::CSLSMapPublisher() 39 | { 40 | } 41 | CSLSMapPublisher::~CSLSMapPublisher() 42 | { 43 | clear(); 44 | } 45 | 46 | void CSLSMapPublisher::set_conf(std::string key, sls_conf_base_t* ca) 47 | { 48 | CSLSLock lock(&m_rwclock, true); 49 | m_map_uplive_2_conf[key] = ca; 50 | } 51 | 52 | void CSLSMapPublisher::set_live_2_uplive(std::string strLive, std::string strUplive) 53 | { 54 | CSLSLock lock(&m_rwclock, true); 55 | m_map_live_2_uplive[strLive] = strUplive; 56 | } 57 | 58 | int CSLSMapPublisher::set_push_2_pushlisher(std::string app_streamname, CSLSRole * role) 59 | { 60 | CSLSLock lock(&m_rwclock, true); 61 | std::map::iterator it; 62 | it = m_map_push_2_pushlisher.find(app_streamname); 63 | if (it != m_map_push_2_pushlisher.end()) { 64 | CSLSRole *cur_role = it->second; 65 | if (NULL != cur_role) { 66 | sls_log(SLS_LOG_INFO, "[%p]CSLSMapPublisher::set_push_2_pushlisher, failed, cur_role=%p, exist, app_streamname=%s, m_map_push_2_pushlisher.size()=%d.", 67 | this, cur_role, app_streamname.c_str(), m_map_push_2_pushlisher.size()); 68 | return SLS_ERROR; 69 | } 70 | } 71 | 72 | m_map_push_2_pushlisher[app_streamname] = role; 73 | sls_log(SLS_LOG_INFO, "[%p]CSLSMapPublisher::set_push_2_pushlisher, ok, %s=%p, app_streamname=%s, m_map_push_2_pushlisher.size()=%d.", 74 | this, role->get_role_name(), role, app_streamname.c_str(), m_map_push_2_pushlisher.size()); 75 | return SLS_OK; 76 | } 77 | 78 | std::string CSLSMapPublisher::get_uplive(std::string key_app) 79 | { 80 | CSLSLock lock(&m_rwclock, false); 81 | std::string uplive_app = ""; 82 | std::map::iterator it; 83 | it = m_map_live_2_uplive.find(key_app);//is publiser? 84 | if (it == m_map_live_2_uplive.end()) { 85 | return uplive_app; 86 | } 87 | uplive_app = it->second; 88 | return uplive_app; 89 | } 90 | 91 | 92 | sls_conf_base_t * CSLSMapPublisher::get_ca(std::string key_app) 93 | { 94 | CSLSLock lock(&m_rwclock, false); 95 | sls_conf_base_t * ca = NULL; 96 | std::map::iterator it; 97 | it = m_map_uplive_2_conf.find(key_app); 98 | if (it == m_map_uplive_2_conf.end()) { 99 | return ca; 100 | } 101 | ca = it->second; 102 | return ca; 103 | } 104 | 105 | CSLSRole * CSLSMapPublisher::get_publisher(std::string strAppStreamName) 106 | { 107 | CSLSLock lock(&m_rwclock, false); 108 | 109 | CSLSRole * publisher = NULL; 110 | std::map::iterator item; 111 | item = m_map_push_2_pushlisher.find(strAppStreamName); 112 | if (item != m_map_push_2_pushlisher.end()) { 113 | publisher = item->second; 114 | } 115 | return publisher; 116 | } 117 | 118 | std::vector CSLSMapPublisher::get_publisher_names() { 119 | std::vector ret; 120 | for (auto val : m_map_push_2_pushlisher) { 121 | std::string streamName = val.first; 122 | ret.push_back(streamName); 123 | } 124 | return ret; 125 | } 126 | 127 | int CSLSMapPublisher::remove(CSLSRole *role) 128 | { 129 | int ret = SLS_ERROR; 130 | 131 | CSLSLock lock(&m_rwclock, true); 132 | 133 | std::map::iterator it; 134 | std::map::iterator it_erase; 135 | for(it=m_map_push_2_pushlisher.begin(); it!=m_map_push_2_pushlisher.end(); ) { 136 | std::string live_stream_name = it->first; 137 | CSLSRole * pub = it->second; 138 | if (role == pub) { 139 | sls_log(SLS_LOG_INFO, "[%p]CSLSMapPublisher::remove, %s=%p, live_key=%s.", 140 | this, pub->get_role_name(), pub, live_stream_name.c_str()); 141 | it_erase = it; 142 | it ++; 143 | m_map_push_2_pushlisher.erase(it_erase); 144 | ret = SLS_OK; 145 | break; 146 | } else { 147 | it ++; 148 | } 149 | } 150 | return ret; 151 | } 152 | 153 | void CSLSMapPublisher::clear() 154 | { 155 | CSLSLock lock(&m_rwclock, true); 156 | sls_log(SLS_LOG_INFO, "[%p]CSLSMapPublisher::clear.", 157 | this); 158 | m_map_push_2_pushlisher.clear(); 159 | m_map_live_2_uplive.clear(); 160 | m_map_uplive_2_conf.clear(); 161 | } 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /slscore/SLSMapPublisher.hpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #ifndef _SLSMapPublisher_INCLUDE_ 27 | #define _SLSMapPublisher_INCLUDE_ 28 | 29 | #include 30 | #include 31 | 32 | #include "conf.hpp" 33 | #include "SLSLock.hpp" 34 | #include "SLSRole.hpp" 35 | 36 | class CSLSMapPublisher 37 | { 38 | public: 39 | CSLSMapPublisher(); 40 | virtual ~CSLSMapPublisher(); 41 | 42 | void set_conf(std::string key, sls_conf_base_t * ca); 43 | void set_live_2_uplive(std::string strLive, std::string strUplive); 44 | int set_push_2_pushlisher(std::string app_streamname, CSLSRole * role); 45 | int remove(CSLSRole *role); 46 | void clear(); 47 | 48 | std::string get_uplive(std::string key_app); 49 | sls_conf_base_t *get_ca(std::string key_app); 50 | 51 | CSLSRole * get_publisher(std::string strAppStreamName); 52 | std::vector get_publisher_names(); 53 | 54 | 55 | private: 56 | std::map m_map_live_2_uplive; // 'hostname/live':'hostname/uplive' 57 | std::map m_map_uplive_2_conf; // 'hostname/uplive':sls_app_conf_t 58 | std::map m_map_push_2_pushlisher; // 'hostname/uplive/steam_name':publisher' 59 | 60 | CSLSRWLock m_rwclock; 61 | 62 | 63 | }; 64 | 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /slscore/SLSMapRelay.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #include "SLSMapRelay.hpp" 27 | 28 | #include 29 | #include 30 | 31 | #include "SLSPullerManager.hpp" 32 | #include "SLSPusherManager.hpp" 33 | #include "SLSLog.hpp" 34 | 35 | 36 | /** 37 | * CSLSMapRelay class implementation 38 | */ 39 | 40 | CSLSMapRelay::CSLSMapRelay() 41 | { 42 | } 43 | 44 | CSLSMapRelay::~CSLSMapRelay() 45 | { 46 | clear(); 47 | } 48 | 49 | CSLSRelayManager * CSLSMapRelay::add_relay_manager(const char *app_uplive, const char *stream_name) 50 | { 51 | //find conf info 52 | SLS_RELAY_INFO * sri = get_relay_conf(std::string(app_uplive)); 53 | if (NULL == sri) { 54 | sls_log(SLS_LOG_INFO, "[%p]CSLSMapRelay::add_relay_manager, no relay conf info, app_uplive=%s, stream_name=%s.", 55 | this, app_uplive, stream_name); 56 | return NULL; 57 | } 58 | 59 | std::string key_stream_name = std::string(app_uplive) + std::string("/") + std::string(stream_name); 60 | CSLSLock lock(&m_rwclock, true); 61 | CSLSRelayManager * cur_mananger = NULL; 62 | std::map::iterator item; 63 | item = m_map_relay_manager.find(key_stream_name); 64 | if (item != m_map_relay_manager.end()) { 65 | cur_mananger = item->second; 66 | if (NULL != cur_mananger) { 67 | sls_log(SLS_LOG_INFO, "[%p]CSLSMapRelay::add, cur_mananger=%p, exist, app_uplive=%s, stream_name=%s.", 68 | this, app_uplive, stream_name, cur_mananger); 69 | return cur_mananger; 70 | } 71 | } 72 | 73 | if (strcmp(sri->m_type, "pull") == 0) 74 | cur_mananger = new CSLSPullerManager; 75 | else if (strcmp(sri->m_type, "push") == 0) 76 | cur_mananger = new CSLSPusherManager; 77 | else { 78 | sls_log(SLS_LOG_INFO, "[%p]CSLSMapRelay::add, failed, wrong , app_uplive=%s, stream_name=%s.", 79 | this, app_uplive, stream_name, cur_mananger); 80 | return NULL; 81 | } 82 | cur_mananger->set_relay_conf(sri); 83 | cur_mananger->set_relay_info(app_uplive, stream_name); 84 | 85 | m_map_relay_manager[key_stream_name] = cur_mananger ; 86 | sls_log(SLS_LOG_INFO, "[%p]CSLSMapRelay::add_relay_manager, ok, app_uplive=%s, stream_name=%s, cur_mananger=%p.", 87 | this, app_uplive, stream_name, cur_mananger); 88 | return cur_mananger; 89 | } 90 | 91 | void CSLSMapRelay::clear() 92 | { 93 | CSLSLock lock(&m_rwclock, true); 94 | sls_log(SLS_LOG_INFO, "[%p]CSLSMapRelay::clear.", 95 | this); 96 | 97 | std::map::iterator it; 98 | for(it=m_map_relay_manager.begin(); it!=m_map_relay_manager.end(); ) { 99 | CSLSRelayManager * relay_manager = it->second; 100 | if (NULL != relay_manager) { 101 | delete relay_manager; 102 | } 103 | it ++; 104 | } 105 | m_map_relay_manager.clear(); 106 | 107 | std::map::iterator it_sri; 108 | for(it_sri=m_map_relay_info.begin(); it_sri!=m_map_relay_info.end(); ) { 109 | SLS_RELAY_INFO * sri = it_sri->second; 110 | if (NULL != sri) { 111 | delete sri; 112 | } 113 | it_sri ++; 114 | } 115 | m_map_relay_info.clear(); 116 | } 117 | 118 | int CSLSMapRelay::add_relay_conf(std::string app_uplive, sls_conf_relay_t * cr) 119 | { 120 | if (NULL == cr) { 121 | sls_log(SLS_LOG_INFO, "[%p]CSLSMapRelay::add_app_conf, failed, cr is null.", 122 | this); 123 | return SLS_ERROR; 124 | } 125 | 126 | SLS_RELAY_INFO * sri = get_relay_conf(app_uplive); 127 | if (NULL != sri) { 128 | sls_log(SLS_LOG_INFO, "[%p]CSLSMapRelay::add_app_conf, failed, sri exist, app_uplive=%s.", 129 | this, app_uplive.c_str()); 130 | return SLS_ERROR; 131 | } 132 | sri = new SLS_RELAY_INFO; 133 | strcpy(sri->m_type, cr->type); 134 | sri->m_reconnect_interval = cr->reconnect_interval; 135 | sri->m_idle_streams_timeout = cr->idle_streams_timeout; 136 | 137 | if (strcmp(cr->mode, "loop") == 0) { 138 | sri->m_mode = SLS_PM_LOOP; 139 | } else if (strcmp(cr->mode, "all") == 0) { 140 | sri->m_mode = SLS_PM_ALL; 141 | } else if (strcmp(cr->mode, "hash") == 0) { 142 | sri->m_mode = SLS_PM_HASH; 143 | } else { 144 | sri->m_mode = SLS_PM_HASH; 145 | sls_log(SLS_LOG_INFO, "[%p]CSLSMapRelay::add_app_conf, wrong mode='%s', use default SLS_PM_LOOP.", 146 | this, cr->mode); 147 | } 148 | 149 | //parse upstreams 150 | sri->m_upstreams = sls_conf_string_split(string(cr->upstreams), string(" ")); 151 | if (sri->m_upstreams.size() == 0) { 152 | sls_log(SLS_LOG_INFO, "[%p]CSLSMapRelay::add_app_conf, wrong upstreams='%s'.", this, cr->upstreams); 153 | } 154 | m_map_relay_info[app_uplive] = sri; 155 | return SLS_OK; 156 | 157 | } 158 | 159 | SLS_RELAY_INFO *CSLSMapRelay::get_relay_conf(std::string app_uplive) 160 | { 161 | SLS_RELAY_INFO * sri = NULL; 162 | std::map::iterator item; 163 | item = m_map_relay_info.find(app_uplive); 164 | if (item != m_map_relay_info.end()) { 165 | sri = item->second; 166 | } 167 | return sri; 168 | 169 | } 170 | 171 | 172 | 173 | 174 | -------------------------------------------------------------------------------- /slscore/SLSMapRelay.hpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #ifndef _SLSMapRelay_INCLUDE_ 27 | #define _SLSMapRelay_INCLUDE_ 28 | 29 | #include 30 | #include 31 | 32 | #include "SLSRelayManager.hpp" 33 | #include "SLSLock.hpp" 34 | 35 | class CSLSMapRelay 36 | { 37 | public: 38 | CSLSMapRelay(); 39 | virtual ~CSLSMapRelay(); 40 | 41 | CSLSRelayManager *add_relay_manager(const char *app_uplive, const char *stream_name); 42 | void clear(); 43 | 44 | int add_relay_conf(std::string app_uplive, sls_conf_relay_t * cr); 45 | SLS_RELAY_INFO *get_relay_conf(std::string app_uplive); 46 | 47 | private: 48 | CSLSRWLock m_rwclock; 49 | std::map m_map_relay_manager; //stream_name: relay_manager 50 | 51 | std::map m_map_relay_info; //uplive: relay_conf_info 52 | }; 53 | 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /slscore/SLSPlayer.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #include 27 | #include 28 | 29 | 30 | #include "SLSPlayer.hpp" 31 | #include "SLSLog.hpp" 32 | 33 | /** 34 | * CSLSPlayer class implementation 35 | */ 36 | 37 | CSLSPlayer::CSLSPlayer() 38 | { 39 | m_is_write = 1; 40 | 41 | sprintf(m_role_name, "player"); 42 | } 43 | 44 | CSLSPlayer::~CSLSPlayer() 45 | { 46 | } 47 | 48 | 49 | 50 | int CSLSPlayer::handler() 51 | { 52 | return handler_write_data() ; 53 | } 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /slscore/SLSPlayer.hpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #ifndef _SLSPlayer_INCLUDE_ 27 | #define _SLSPlayer_INCLUDE_ 28 | 29 | #include "SLSRole.hpp" 30 | 31 | /** 32 | * CSLSPlayer 33 | */ 34 | class CSLSPlayer: public CSLSRole 35 | { 36 | public : 37 | CSLSPlayer(); 38 | ~CSLSPlayer(); 39 | 40 | virtual int handler(); 41 | 42 | private: 43 | 44 | 45 | }; 46 | 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /slscore/SLSPublisher.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #include 27 | #include 28 | 29 | 30 | #include "SLSPublisher.hpp" 31 | #include "SLSPlayer.hpp" 32 | #include "SLSLog.hpp" 33 | 34 | /** 35 | * app conf 36 | */ 37 | SLS_CONF_DYNAMIC_IMPLEMENT(app) 38 | 39 | /** 40 | * CSLSPublisher class implementation 41 | */ 42 | 43 | CSLSPublisher::CSLSPublisher() 44 | { 45 | m_is_write = 0; 46 | m_map_publisher = NULL; 47 | 48 | sprintf(m_role_name, "publisher"); 49 | 50 | } 51 | 52 | CSLSPublisher::~CSLSPublisher() 53 | { 54 | //release 55 | } 56 | 57 | int CSLSPublisher::init() 58 | { 59 | int ret = CSLSRole::init(); 60 | if (m_conf) { 61 | sls_conf_app_t * app_conf = ((sls_conf_app_t *)m_conf); 62 | //m_exit_delay = ((sls_conf_app_t *)m_conf)->publisher_exit_delay; 63 | strcpy(m_record_hls, app_conf->record_hls); 64 | m_record_hls_segment_duration = app_conf->record_hls_segment_duration; 65 | } 66 | 67 | return ret; 68 | } 69 | 70 | int CSLSPublisher::uninit() 71 | { 72 | int ret = SLS_OK; 73 | 74 | if (m_map_data) { 75 | ret = m_map_data->remove(m_map_data_key); 76 | sls_log(SLS_LOG_INFO, "[%p]CSLSPublisher::uninit, removed publisher from m_map_data, ret=%d.", 77 | this, ret); 78 | } 79 | 80 | if (m_map_publisher) { 81 | ret = m_map_publisher->remove(this); 82 | sls_log(SLS_LOG_INFO, "[%p]CSLSPublisher::uninit, removed publisher from m_map_publisher, ret=%d.", 83 | this, ret); 84 | } 85 | return CSLSRole::uninit(); 86 | } 87 | 88 | void CSLSPublisher::set_map_publisher(CSLSMapPublisher * publisher) 89 | { 90 | m_map_publisher = publisher; 91 | } 92 | 93 | int CSLSPublisher::handler() 94 | { 95 | return handler_read_data(); 96 | } 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /slscore/SLSPublisher.hpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #ifndef _SLSPublisher_INCLUDE_ 27 | #define _SLSPublisher_INCLUDE_ 28 | 29 | #include 30 | 31 | #include "SLSRole.hpp" 32 | #include "SLSRoleList.hpp" 33 | #include "SLSMapPublisher.hpp" 34 | 35 | /** 36 | * sls_conf_app_t 37 | */ 38 | SLS_CONF_DYNAMIC_DECLARE_BEGIN(app) 39 | char app_player[STR_MAX_LEN]; 40 | char app_publisher[STR_MAX_LEN]; 41 | int publisher_exit_delay; 42 | char record_hls[SHORT_STR_MAX_LEN]; 43 | int record_hls_segment_duration; 44 | SLS_CONF_DYNAMIC_DECLARE_END 45 | 46 | /** 47 | * app cmd declare 48 | */ 49 | SLS_CONF_CMD_DYNAMIC_DECLARE_BEGIN(app) 50 | SLS_SET_CONF(app, string, app_player, "live", 1, STR_MAX_LEN-1), 51 | SLS_SET_CONF(app, string, app_publisher, "uplive", 1, STR_MAX_LEN-1), 52 | SLS_SET_CONF(app, int, publisher_exit_delay, "delay exit time, unit second.", 1, 300), 53 | SLS_SET_CONF(app, string, record_hls, "record_hls switch", 1, SHORT_STR_MAX_LEN-1), 54 | SLS_SET_CONF(app, int, record_hls_segment_duration, "record_hls_segment_duration", 1, 3600), 55 | SLS_CONF_CMD_DYNAMIC_DECLARE_END 56 | 57 | 58 | /** 59 | * CSLSPublisher 60 | */ 61 | class CSLSPublisher: public CSLSRole 62 | { 63 | public : 64 | CSLSPublisher(); 65 | virtual ~CSLSPublisher(); 66 | 67 | void set_map_publisher(CSLSMapPublisher * publisher); 68 | 69 | virtual int init(); 70 | virtual int uninit(); 71 | 72 | virtual int handler(); 73 | private: 74 | CSLSMapPublisher * m_map_publisher; 75 | 76 | }; 77 | 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /slscore/SLSPuller.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #include 27 | #include 28 | 29 | 30 | #include "SLSPuller.hpp" 31 | #include "SLSLog.hpp" 32 | #include "SLSMapRelay.hpp" 33 | 34 | const char SLS_RELAY_STAT_INFO_BASE[] = "\ 35 | {\ 36 | \"port\": \"%d\",\ 37 | \"role\": \"%s\",\ 38 | \"pub_domain_app\": \"%s\",\ 39 | \"stream_name\": \"%s\",\ 40 | \"url\": \"%s\",\ 41 | \"remote_ip\": \"%s\",\ 42 | \"remote_port\": \"%d\",\ 43 | \"start_time\": \"%s\",\ 44 | \"kbitrate\":\ 45 | "; 46 | 47 | /** 48 | * CSLSPuller class implementation 49 | */ 50 | 51 | CSLSPuller::CSLSPuller() 52 | { 53 | m_is_write = 0; 54 | sprintf(m_role_name, "puller"); 55 | 56 | } 57 | 58 | int CSLSPuller::uninit() 59 | { 60 | int ret = SLS_ERROR; 61 | if (NULL != m_map_publisher) { 62 | ret = m_map_publisher->remove(this); 63 | sls_log(SLS_LOG_INFO, "[%p]CSLSPuller::uninit, removed relay from m_map_publisher, ret=%d.", 64 | this, ret); 65 | } 66 | if (m_map_data) { 67 | ret = m_map_data->remove(m_map_data_key); 68 | sls_log(SLS_LOG_INFO, "[%p]CSLSPuller::uninit, removed relay from m_map_data, ret=%d.", 69 | this, ret); 70 | } 71 | return CSLSRelay::uninit(); 72 | 73 | } 74 | 75 | CSLSPuller::~CSLSPuller() 76 | { 77 | //release 78 | } 79 | 80 | int CSLSPuller::handler() 81 | { 82 | int64_t last_read_time = 0; 83 | int ret = handler_read_data(&last_read_time); 84 | if (ret >= 0) { 85 | //*check if there is any player? 86 | if (-1 == m_idle_streams_timeout) { 87 | return ret; 88 | } 89 | int64_t cur_time = sls_gettime_ms(); 90 | if (cur_time - last_read_time >= (m_idle_streams_timeout*1000)) { 91 | sls_log(SLS_LOG_INFO, "[%p]CSLSPuller::handler, no any reader for m_idle_streams_timeout=%ds, last_read_time=%lld, close puller.", 92 | this, m_idle_streams_timeout, last_read_time); 93 | m_state = SLS_RS_INVALID; 94 | invalid_srt(); 95 | return SLS_ERROR; 96 | } 97 | //*/ 98 | } 99 | return ret; 100 | } 101 | 102 | int CSLSPuller::get_stat_base(char *stat_base) 103 | { 104 | strcpy(stat_base, SLS_RELAY_STAT_INFO_BASE); 105 | return SLS_OK; 106 | } 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /slscore/SLSPuller.hpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #ifndef _SLSPuller_INCLUDE_ 27 | #define _SLSPuller_INCLUDE_ 28 | 29 | #include "SLSRelay.hpp" 30 | 31 | /** 32 | * CSLSPuller 33 | */ 34 | class CSLSPuller: public CSLSRelay 35 | { 36 | public : 37 | CSLSPuller(); 38 | virtual ~CSLSPuller(); 39 | 40 | virtual int uninit(); 41 | virtual int handler(); 42 | virtual int get_stat_base(char *stat_base); 43 | protected: 44 | 45 | }; 46 | 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /slscore/SLSPullerManager.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #include 27 | #include 28 | 29 | #include "common.hpp" 30 | #include "SLSPullerManager.hpp" 31 | #include "SLSLog.hpp" 32 | #include "SLSPuller.hpp" 33 | 34 | /** 35 | * CSLSPullerManager class implementation 36 | */ 37 | 38 | CSLSPullerManager::CSLSPullerManager() 39 | { 40 | m_cur_loop_index = -1; 41 | } 42 | 43 | CSLSPullerManager::~CSLSPullerManager() 44 | { 45 | } 46 | 47 | 48 | //start to connect from next of cur index per time. 49 | int CSLSPullerManager::connect_loop() 50 | { 51 | int ret = SLS_ERROR; 52 | 53 | if (m_sri == NULL || m_sri->m_upstreams.size() == 0) { 54 | sls_log(SLS_LOG_INFO, "[%p]CSLSPullerManager::connect_loop, failed, m_upstreams.size()=0, m_app_uplive=%s, m_stream_name=%s.", 55 | this, m_app_uplive, m_stream_name); 56 | return ret; 57 | } 58 | 59 | CSLSRelay *puller = NULL; 60 | if (-1 == m_cur_loop_index) { 61 | m_cur_loop_index = m_sri->m_upstreams.size() - 1; 62 | } 63 | int index = m_cur_loop_index ; 64 | index ++; 65 | 66 | char szURL[1024] = {0}; 67 | while (true) { 68 | if (index >= m_sri->m_upstreams.size()) 69 | index = 0; 70 | 71 | const char *szTmp = m_sri->m_upstreams[index].c_str(); 72 | sprintf(szURL, "srt://%s/%s", szTmp, m_stream_name); 73 | ret = connect(szURL); 74 | if (SLS_OK == ret) { 75 | break; 76 | } 77 | if (index == m_cur_loop_index) { 78 | sls_log(SLS_LOG_INFO, "[%p]CSLSPullerManager::connect_loop, failed, no available pullers, m_app_uplive=%s, m_stream_name=%s.", 79 | this, m_app_uplive, m_stream_name); 80 | break; 81 | } 82 | sls_log(SLS_LOG_INFO, "[%p]CSLSPullerManager::connect_loop, failed, index=%d, m_app_uplive=%s, m_stream_name=%s, szURL=‘%s’.", 83 | this, m_app_uplive, m_stream_name, szURL); 84 | index ++; 85 | } 86 | m_cur_loop_index = index; 87 | return ret; 88 | } 89 | 90 | int CSLSPullerManager::start() 91 | { 92 | int ret = SLS_ERROR; 93 | 94 | if (NULL == m_sri) { 95 | sls_log(SLS_LOG_INFO, "[%p]CSLSPullerManager::start, failed, m_upstreams.size()=0, m_app_uplive=%s, m_stream_name=%s.", 96 | this, m_app_uplive, m_stream_name); 97 | return ret; 98 | } 99 | 100 | //check publisher 101 | char key_stream_name[1024] = {0}; 102 | sprintf(key_stream_name, "%s/%s", m_app_uplive, m_stream_name); 103 | if (NULL != m_map_publisher) { 104 | CSLSRole * publisher = m_map_publisher->get_publisher(key_stream_name); 105 | if (NULL != publisher) { 106 | sls_log(SLS_LOG_INFO, "[%p]CSLSPullerManager::start, failed, key_stream_name=%s, publisher=%p exist.", 107 | this, key_stream_name, publisher); 108 | return ret; 109 | } 110 | } 111 | 112 | 113 | if (SLS_PM_LOOP == m_sri->m_mode) { 114 | ret = connect_loop(); 115 | } else if (SLS_PM_HASH == m_sri->m_mode) { 116 | ret = connect_hash(); 117 | } else { 118 | sls_log(SLS_LOG_INFO, "[%p]CSLSPullerManager::start, failed, wrong m_sri->m_mode=%d, m_app_uplive=%s, m_stream_name=%s.", 119 | this, m_sri->m_mode, m_app_uplive, m_stream_name); 120 | } 121 | return ret; 122 | } 123 | 124 | CSLSRelay *CSLSPullerManager::create_relay() 125 | { 126 | CSLSRelay * relay = new CSLSPuller; 127 | return relay; 128 | } 129 | 130 | int CSLSPullerManager::check_relay_param() 131 | { 132 | if (NULL == m_role_list) { 133 | sls_log(SLS_LOG_WARNING, "[%p]CSLSRelayManager::check_relay_param, failed, m_role_list is null, stream=%s.", 134 | this, m_stream_name); 135 | return SLS_ERROR; 136 | } 137 | if (NULL == m_map_publisher) { 138 | sls_log(SLS_LOG_WARNING, "[%p]CSLSRelayManager::check_relay_param, failed, m_map_publisher is null, stream=%s.", 139 | this, m_stream_name); 140 | return SLS_ERROR; 141 | } 142 | if (NULL == m_map_data) { 143 | sls_log(SLS_LOG_WARNING, "[%p]CSLSRelayManager::check_relay_param, failed, m_map_data is null, stream=%s.", 144 | this, m_stream_name); 145 | return SLS_ERROR; 146 | } 147 | return SLS_OK; 148 | 149 | } 150 | 151 | int CSLSPullerManager::set_relay_param(CSLSRelay *relay) 152 | { 153 | char key_stream_name[1024] = {0}; 154 | sprintf(key_stream_name, "%s/%s", m_app_uplive, m_stream_name); 155 | 156 | if (SLS_OK != check_relay_param()){ 157 | sls_log(SLS_LOG_WARNING, "[%p]CSLSRelayManager::set_relay_param, check_relay_param failed, stream=%s.", 158 | this, key_stream_name); 159 | return SLS_ERROR; 160 | } 161 | 162 | if (SLS_OK != m_map_publisher->set_push_2_pushlisher(key_stream_name, relay)) { 163 | sls_log(SLS_LOG_WARNING, "[%p]CSLSRelayManager::set_relay_param, m_map_publisher->set_push_2_pushlisher, stream=%s.", 164 | this, key_stream_name); 165 | return SLS_ERROR; 166 | } 167 | 168 | if (SLS_OK != m_map_data->add(key_stream_name)) { 169 | sls_log(SLS_LOG_WARNING, "[%p]CSLSRelayManager::set_relay_param, m_map_data->add failed, stream=%s, remove from relay=%p, m_map_publisher.", 170 | this, key_stream_name, relay); 171 | m_map_publisher->remove(relay); 172 | return SLS_ERROR; 173 | } 174 | 175 | relay->set_map_data(key_stream_name, m_map_data); 176 | relay->set_map_publisher(m_map_publisher); 177 | relay->set_relay_manager(this); 178 | m_role_list->push(relay); 179 | 180 | return SLS_OK; 181 | 182 | } 183 | 184 | int CSLSPullerManager::add_reconnect_stream(char* relay_url) 185 | { 186 | m_reconnect_begin_tm = sls_gettime_ms(); 187 | } 188 | 189 | int CSLSPullerManager::reconnect(int64_t cur_tm_ms) 190 | { 191 | int ret = SLS_ERROR; 192 | if (cur_tm_ms - m_reconnect_begin_tm < (m_sri->m_reconnect_interval * 1000)) { 193 | return ret; 194 | } 195 | m_reconnect_begin_tm = cur_tm_ms; 196 | 197 | if (SLS_OK != check_relay_param()) { 198 | sls_log(SLS_LOG_WARNING, "[%p]CSLSPullerManager::reconnect, check_relay_param failed, stream=%s.", 199 | this, m_stream_name); 200 | return SLS_ERROR; 201 | } 202 | 203 | char key_stream_name[1024] = {0}; 204 | sprintf(key_stream_name, "%s/%s", m_app_uplive, m_stream_name); 205 | 206 | ret = start(); 207 | if (SLS_OK != ret) { 208 | sls_log(SLS_LOG_INFO, "[%p]CSLSPullerManager::reconnect, start failed, key_stream_name=%s.", 209 | this, key_stream_name); 210 | } else { 211 | sls_log(SLS_LOG_INFO, "[%p]CSLSPullerManager::reconnect, start ok, key_stream_name=%s.", 212 | this, key_stream_name); 213 | } 214 | return ret; 215 | } 216 | 217 | -------------------------------------------------------------------------------- /slscore/SLSPullerManager.hpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #ifndef _SLSPulllerManager_INCLUDE_ 27 | #define _SLSPulllerManager_INCLUDE_ 28 | 29 | #include 30 | #include 31 | 32 | #include "SLSRelayManager.hpp" 33 | #include "conf.hpp" 34 | 35 | /** 36 | * CSLSPullerManager 37 | */ 38 | class CSLSPullerManager: public CSLSRelayManager 39 | { 40 | public : 41 | CSLSPullerManager(); 42 | virtual ~CSLSPullerManager(); 43 | 44 | virtual int start(); 45 | virtual int add_reconnect_stream(char* relay_url); 46 | virtual int reconnect(int64_t cur_tm_ms); 47 | 48 | protected: 49 | 50 | int connect_loop(); 51 | virtual CSLSRelay *create_relay(); 52 | virtual int set_relay_param(CSLSRelay *relay); 53 | int check_relay_param(); 54 | 55 | int m_cur_loop_index; 56 | 57 | }; 58 | 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /slscore/SLSPusher.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #include 27 | #include 28 | 29 | 30 | #include "SLSPusher.hpp" 31 | #include "SLSLog.hpp" 32 | 33 | const char SLS_RELAY_STAT_INFO_BASE[] = "\ 34 | {\ 35 | \"port\": \"%d\",\ 36 | \"role\": \"%s\",\ 37 | \"pub_domain_app\": \"%s\",\ 38 | \"stream_name\": \"%s\",\ 39 | \"url\": \"%s\",\ 40 | \"remote_ip\": \"%s\",\ 41 | \"remote_port\": \"%d\",\ 42 | \"start_time\": \"%s\",\ 43 | \"kbitrate\":\ 44 | "; 45 | 46 | /** 47 | * CSLSPusher class implementation 48 | */ 49 | 50 | CSLSPusher::CSLSPusher() 51 | { 52 | m_is_write = 1; 53 | sprintf(m_role_name, "pusher"); 54 | 55 | } 56 | 57 | CSLSPusher::~CSLSPusher() 58 | { 59 | //release 60 | } 61 | 62 | int CSLSPusher::handler() 63 | { 64 | return handler_write_data(); 65 | } 66 | 67 | int CSLSPusher::get_stat_base(char *stat_base) 68 | { 69 | strcpy(stat_base, SLS_RELAY_STAT_INFO_BASE); 70 | return SLS_OK; 71 | } 72 | 73 | 74 | -------------------------------------------------------------------------------- /slscore/SLSPusher.hpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #ifndef _SLSPusher_INCLUDE_ 27 | #define _SLSPusher_INCLUDE_ 28 | 29 | #include "SLSRelay.hpp" 30 | 31 | /** 32 | * CSLSPuller 33 | */ 34 | class CSLSPusher: public CSLSRelay 35 | { 36 | public : 37 | CSLSPusher(); 38 | virtual ~CSLSPusher(); 39 | 40 | virtual int handler(); 41 | virtual int get_stat_base(char *stat_base); 42 | protected: 43 | 44 | }; 45 | 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /slscore/SLSPusherManager.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #include 27 | #include 28 | 29 | #include "common.hpp" 30 | #include "SLSPusherManager.hpp" 31 | #include "SLSLog.hpp" 32 | #include "SLSPusher.hpp" 33 | 34 | /** 35 | * CSLSPusherManager class implementation 36 | */ 37 | 38 | CSLSPusherManager::CSLSPusherManager() 39 | { 40 | } 41 | 42 | CSLSPusherManager::~CSLSPusherManager() 43 | { 44 | } 45 | 46 | //start to connect from next of cur index per time. 47 | int CSLSPusherManager::connect_all() 48 | { 49 | int ret = SLS_ERROR; 50 | if (m_sri == NULL) { 51 | sls_log(SLS_LOG_INFO, "[%p]CSLSPusherManager::connect_all, failed, m_upstreams.size()=0, m_app_uplive=%s, m_stream_name=%s.", 52 | this, m_app_uplive, m_stream_name); 53 | return ret; 54 | } 55 | 56 | int all_ret = SLS_OK; 57 | for (int i = 0; i < m_sri->m_upstreams.size(); i ++) { 58 | char szURL[1024] = {0}; 59 | const char *szTmp = m_sri->m_upstreams[i].c_str(); 60 | sprintf(szURL, "srt://%s/%s", szTmp, m_stream_name); 61 | ret = connect(szURL); 62 | if (SLS_OK != ret) { 63 | CSLSLock lock(&m_rwclock, true); 64 | m_map_reconnect_relay[std::string(szURL)] = sls_gettime_ms(); 65 | } 66 | all_ret |= ret; 67 | } 68 | return all_ret; 69 | } 70 | 71 | int CSLSPusherManager::start() 72 | { 73 | int ret = SLS_ERROR; 74 | if (m_sri == NULL) { 75 | sls_log(SLS_LOG_INFO, "[%p]CSLSPusherManager::start, failed, m_upstreams.size()=0, m_app_uplive=%s, m_stream_name=%s.", 76 | this, m_app_uplive, m_stream_name); 77 | return ret; 78 | } 79 | 80 | //check publisher 81 | char key_stream_name[URL_MAX_LEN] = {0}; 82 | sprintf(key_stream_name, "%s/%s", m_app_uplive, m_stream_name); 83 | if (NULL != m_map_publisher) { 84 | CSLSRole * publisher = m_map_publisher->get_publisher(key_stream_name); 85 | if (NULL == publisher) { 86 | sls_log(SLS_LOG_INFO, "[%p]CSLSPullerManager::start, failed, key_stream_name=%s, publisher=NULL not exist.", 87 | this, key_stream_name); 88 | return ret; 89 | } 90 | } 91 | 92 | if (SLS_PM_ALL == m_sri->m_mode) { 93 | return connect_all(); 94 | } else if (SLS_PM_HASH == m_sri->m_mode) { 95 | ret = connect_hash(); 96 | } else { 97 | sls_log(SLS_LOG_INFO, "[%p]CSLSPusherManager::start, failed, wrong m_sri->m_mode=%d, m_app_uplive=%s, m_stream_name=%s.", 98 | this, m_sri->m_mode, m_app_uplive, m_stream_name); 99 | } 100 | return ret; 101 | } 102 | 103 | CSLSRelay *CSLSPusherManager::create_relay() 104 | { 105 | CSLSRelay * relay = new CSLSPusher; 106 | return relay; 107 | } 108 | 109 | int CSLSPusherManager::set_relay_param(CSLSRelay *relay) 110 | { 111 | char key_stream_name[1024] = {0}; 112 | sprintf(key_stream_name, "%s/%s", m_app_uplive, m_stream_name); 113 | relay->set_map_data(key_stream_name, m_map_data); 114 | relay->set_map_publisher(m_map_publisher); 115 | relay->set_relay_manager(this); 116 | m_role_list->push(relay); 117 | return SLS_OK; 118 | } 119 | 120 | int CSLSPusherManager::add_reconnect_stream(char* relay_url) 121 | { 122 | int ret = SLS_ERROR; 123 | if (m_sri == NULL) { 124 | sls_log(SLS_LOG_INFO, "[%p]CSLSPusherManager::add_reconnect_stream, failed, m_upstreams.size()=0, m_app_uplive=%s, m_stream_name=%s.", 125 | this, m_app_uplive, m_stream_name); 126 | return ret; 127 | } 128 | 129 | if (SLS_PM_ALL == m_sri->m_mode) { 130 | std::string url = std::string(relay_url); 131 | CSLSLock lock(&m_rwclock, true); 132 | int64_t tm = sls_gettime_ms(); 133 | m_map_reconnect_relay[url] = tm; 134 | ret = SLS_OK; 135 | } else if (SLS_PM_HASH == m_sri->m_mode) { 136 | m_reconnect_begin_tm = sls_gettime_ms(); 137 | ret = SLS_OK; 138 | } else { 139 | sls_log(SLS_LOG_INFO, "[%p]CSLSPusherManager::add_reconnect_stream, failed, wrong m_sri->m_mode=%d, m_app_uplive=%s, m_stream_name=%s.", 140 | this, m_sri->m_mode, m_app_uplive, m_stream_name); 141 | } 142 | return ret; 143 | } 144 | 145 | int CSLSPusherManager::reconnect(int64_t cur_tm_ms) 146 | { 147 | int ret = SLS_ERROR; 148 | if (SLS_OK != check_relay_param()) { 149 | sls_log(SLS_LOG_WARNING, "[%p]CSLSPusherManager::reconnect, check_relay_param failed, stream=%s.", 150 | this, m_stream_name); 151 | return ret; 152 | } 153 | 154 | if (m_sri == NULL) { 155 | sls_log(SLS_LOG_INFO, "[%p]CSLSPusherManager::reconnect, failed, m_upstreams.size()=0, m_app_uplive=%s, m_stream_name=%s.", 156 | this, m_app_uplive, m_stream_name); 157 | return ret; 158 | } 159 | 160 | //check publisher 161 | bool no_publisher = false; 162 | char key_stream_name[1024] = {0}; 163 | sprintf(key_stream_name, "%s/%s", m_app_uplive, m_stream_name); 164 | if (NULL != m_map_publisher) { 165 | CSLSRole * publisher = m_map_publisher->get_publisher(key_stream_name); 166 | if (NULL == publisher) { 167 | no_publisher = true; 168 | } 169 | } 170 | 171 | if (SLS_PM_ALL == m_sri->m_mode) { 172 | ret = reconnect_all(cur_tm_ms, no_publisher); 173 | return ret; 174 | } else if (SLS_PM_HASH == m_sri->m_mode) { 175 | if (cur_tm_ms - m_reconnect_begin_tm < (m_sri->m_reconnect_interval * 1000)) { 176 | return ret; 177 | } 178 | m_reconnect_begin_tm = cur_tm_ms; 179 | if (no_publisher) { 180 | sls_log(SLS_LOG_INFO, "[%p]CSLSPullerManager::reconnect, connect_hash failed, key_stream_name=%s, publisher=NULL not exist.", 181 | this, key_stream_name); 182 | return ret; 183 | } 184 | ret = connect_hash(); 185 | } else { 186 | sls_log(SLS_LOG_INFO, "[%p]CSLSPusherManager::reconnect, failed, wrong m_sri->m_mode=%d, m_app_uplive=%s, m_stream_name=%s.", 187 | this, m_sri->m_mode, m_app_uplive, m_stream_name); 188 | } 189 | return ret; 190 | 191 | } 192 | 193 | int CSLSPusherManager::check_relay_param() 194 | { 195 | if (NULL == m_role_list) { 196 | sls_log(SLS_LOG_WARNING, "[%p]CSLSRelayManager::check_relay_param, failed, m_role_list is null, stream=%s.", 197 | this, m_stream_name); 198 | return SLS_ERROR; 199 | } 200 | if (NULL == m_map_data) { 201 | sls_log(SLS_LOG_WARNING, "[%p]CSLSRelayManager::check_relay_param, failed, m_map_data is null, stream=%s.", 202 | this, m_stream_name); 203 | return SLS_ERROR; 204 | } 205 | return SLS_OK; 206 | } 207 | 208 | int CSLSPusherManager::reconnect_all(int64_t cur_tm_ms, bool no_publisher) 209 | { 210 | CSLSLock lock(&m_rwclock, true); 211 | 212 | int ret = SLS_ERROR; 213 | int all_ret = SLS_OK; 214 | std::map::iterator it_cur; 215 | std::map::iterator it; 216 | for(it=m_map_reconnect_relay.begin(); it!=m_map_reconnect_relay.end();) { 217 | std::string url = it->first; 218 | int64_t begin_tm = it->second; 219 | it_cur = it; 220 | it ++; 221 | if (cur_tm_ms - begin_tm < (m_sri->m_reconnect_interval * 1000)) { 222 | all_ret |= ret; 223 | continue; 224 | } 225 | if (no_publisher) { 226 | //it_cur->second = cur_tm_ms; 227 | all_ret |= ret; 228 | m_map_reconnect_relay[url] = cur_tm_ms; 229 | sls_log(SLS_LOG_INFO, "[%p]CSLSPullerManager::reconnect_all, failed, url=%s, publisher=NULL not exist.", 230 | this, url.c_str()); 231 | continue; 232 | } 233 | ret = connect(url.c_str()); 234 | if (SLS_OK != ret) { 235 | sls_log(SLS_LOG_INFO, "[%p]CSLSRelayManager::reconnect_all, faild, connect url='%s'.", 236 | this, url.c_str()); 237 | m_map_reconnect_relay[url] = cur_tm_ms; 238 | } else { 239 | sls_log(SLS_LOG_INFO, "[%p]CSLSRelayManager::reconnect_all, ok, connect url='%s', erase item from m_map_reconnect_relay.", 240 | this, url.c_str()); 241 | m_map_reconnect_relay.erase(it_cur); 242 | } 243 | all_ret |= ret; 244 | } 245 | 246 | return all_ret; 247 | } 248 | 249 | 250 | -------------------------------------------------------------------------------- /slscore/SLSPusherManager.hpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #ifndef _SLSPusherManager_INCLUDE_ 27 | #define _SLSPusherManager_INCLUDE_ 28 | 29 | #include 30 | #include 31 | 32 | #include "SLSRelayManager.hpp" 33 | #include "conf.hpp" 34 | 35 | /** 36 | * CSLSPusherManager 37 | */ 38 | class CSLSPusherManager: public CSLSRelayManager 39 | { 40 | public : 41 | CSLSPusherManager(); 42 | virtual ~CSLSPusherManager(); 43 | 44 | virtual int start(); 45 | virtual int add_reconnect_stream(char* relay_url); 46 | virtual int reconnect(int64_t cur_tm_ms); 47 | 48 | 49 | private: 50 | int connect_all(); 51 | virtual CSLSRelay *create_relay(); 52 | virtual int set_relay_param(CSLSRelay *relay); 53 | int check_relay_param(); 54 | int reconnect_all(int64_t cur_tm_ms, bool no_publisher); 55 | 56 | CSLSRWLock m_rwclock; 57 | std::map m_map_reconnect_relay;//relay:timeout 58 | 59 | }; 60 | 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /slscore/SLSRecycleArray.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #include 27 | 28 | 29 | #include "SLSRecycleArray.hpp" 30 | #include "SLSLog.hpp" 31 | 32 | const int DEFAULT_MAX_DATA_SIZE = 1024*1316;//about 5mbps*2sec 33 | 34 | CSLSRecycleArray::CSLSRecycleArray() 35 | { 36 | m_nDataSize = DEFAULT_MAX_DATA_SIZE; 37 | m_nWritePos = 0; 38 | m_nDataCount = 0; 39 | 40 | m_last_read_time = sls_gettime_ms(); 41 | 42 | m_arrayData = new char[m_nDataSize]; 43 | 44 | } 45 | 46 | CSLSRecycleArray::~CSLSRecycleArray() 47 | { 48 | CSLSLock lock(&m_rwclock, true); 49 | if (m_arrayData != NULL) { 50 | delete[] m_arrayData; 51 | m_arrayData = NULL; 52 | } 53 | } 54 | 55 | int CSLSRecycleArray::count() 56 | { 57 | CSLSLock lock(&m_rwclock, false); 58 | return m_nDataCount; 59 | } 60 | 61 | //please call this function before get and put, 62 | //if not, the read data will be make confusion. 63 | void CSLSRecycleArray::setSize(int n) 64 | { 65 | CSLSLock lock(&m_rwclock, false); 66 | delete[] m_arrayData ; 67 | m_nDataSize = n; 68 | m_nWritePos = 0; 69 | m_arrayData = new char[m_nDataSize]; 70 | } 71 | 72 | int CSLSRecycleArray::put(char * data, int len) 73 | { 74 | if (!data || len <= 0) { 75 | sls_log(SLS_LOG_INFO, "[%p]CSLSRecycleArray::put, failed, data=%p, len=%d.", 76 | this, data, len); 77 | return SLS_ERROR; 78 | } 79 | 80 | if (len > m_nDataSize) { 81 | sls_log(SLS_LOG_INFO, "[%p]CSLSRecycleArray::put, failed, len=%d is bigger than m_nDataSize=%d.", 82 | this, data, len, m_nDataSize); 83 | return SLS_ERROR; 84 | } 85 | 86 | { 87 | CSLSLock lock(&m_rwclock, true); 88 | if (m_nDataSize - m_nWritePos >= len) { 89 | //copy directly 90 | memcpy(m_arrayData + m_nWritePos, data, len); 91 | m_nWritePos += len; 92 | } else { 93 | int first_len = m_nDataSize - m_nWritePos; 94 | memcpy(m_arrayData + m_nWritePos, data, first_len); 95 | memcpy(m_arrayData, data + first_len, len - first_len); 96 | m_nWritePos = (len - first_len); 97 | } 98 | 99 | if (m_nWritePos==m_nDataSize) 100 | m_nWritePos = 0; 101 | } 102 | //no consider int wrapround; 103 | m_nDataCount += len; 104 | sls_log(SLS_LOG_TRACE, "[%p]CSLSRecycleArray::put, len=%d, m_nWritePos=%d, m_nDataCount=%d, m_nDataSize=%d.", 105 | this, len, m_nWritePos, m_nDataCount, m_nDataSize); 106 | return len; 107 | } 108 | 109 | int CSLSRecycleArray::get(char *data, int size, SLSRecycleArrayID *read_id, int aligned) 110 | { 111 | if (NULL == m_arrayData) { 112 | sls_log(SLS_LOG_INFO, "[%p]CSLSRecycleArray::get, failed, m_arrayData is NULL.", this); 113 | return SLS_ERROR; 114 | } 115 | 116 | if (NULL == read_id) { 117 | sls_log(SLS_LOG_INFO, "[%p]CSLSRecycleArray::get, failed, read_id is NULL.", this); 118 | return SLS_ERROR; 119 | } 120 | 121 | if (read_id->bFirst) { 122 | read_id->nReadPos = m_nWritePos; 123 | read_id->nDataCount = m_nDataCount; 124 | read_id->bFirst = false; 125 | sls_log(SLS_LOG_TRACE, "[%p]CSLSRecycleArray::get, the first time."); 126 | return SLS_OK; 127 | } 128 | 129 | CSLSLock lock(&m_rwclock, false); 130 | if (read_id->nReadPos == m_nWritePos && m_nDataCount == read_id->nDataCount) { 131 | sls_log(SLS_LOG_TRACE, "[%p]CSLSRecycleArray::get, no new data.", this); 132 | return SLS_OK; 133 | } 134 | sls_log(SLS_LOG_TRACE, "[%p]CSLSRecycleArray::get, read_id->nReadPos=%d, m_nWritePos=%d, m_nDataCount=%d, m_nDataSize=%d.", 135 | this, read_id->nReadPos, m_nWritePos, m_nDataCount, m_nDataSize); 136 | 137 | //update the last read time 138 | m_last_read_time = sls_gettime_ms(); 139 | 140 | int ready_data_len = 0; 141 | int copy_data_len = 0; 142 | if (read_id->nReadPos < m_nWritePos) { 143 | //read pos is behind in the write pos 144 | ready_data_len = m_nWritePos - read_id->nReadPos; 145 | copy_data_len = ready_data_len <= size ? ready_data_len : size; 146 | if (aligned > 0) { 147 | copy_data_len = copy_data_len/aligned * aligned; 148 | } 149 | //sls_log(SLS_LOG_TRACE, "[%p]CSLSRecycleArray::get, read pos is behind in the write pos, copy_data_len=%d, ready_data_len=%d, size=%d.", 150 | // this, copy_data_len, ready_data_len, size); 151 | if (copy_data_len > 0) { 152 | memcpy(data, m_arrayData + read_id->nReadPos, copy_data_len); 153 | read_id->nReadPos += copy_data_len; 154 | } 155 | } else { 156 | ready_data_len = m_nDataSize - read_id->nReadPos + m_nWritePos; 157 | copy_data_len = ready_data_len <= size ? ready_data_len : size; 158 | if (aligned > 0) { 159 | copy_data_len = copy_data_len/aligned * aligned; 160 | } 161 | //sls_log(SLS_LOG_TRACE, "[%p]CSLSRecycleArray::get, read pos is before of the write pos, copy_data_len=%d, ready_data_len=%d, size=%d.", 162 | // this, copy_data_len, ready_data_len, size); 163 | if (copy_data_len > 0) { 164 | if (m_nDataSize - read_id->nReadPos >= copy_data_len) { 165 | //no wrap round 166 | memcpy(data, m_arrayData + read_id->nReadPos, copy_data_len); 167 | read_id->nReadPos += copy_data_len; 168 | } else { 169 | memcpy(data, m_arrayData + read_id->nReadPos, m_nDataSize - read_id->nReadPos); 170 | //wrap around 171 | memcpy(data + (m_nDataSize - read_id->nReadPos), m_arrayData, copy_data_len - (m_nDataSize - read_id->nReadPos)); 172 | read_id->nReadPos = copy_data_len - (m_nDataSize - read_id->nReadPos); 173 | } 174 | } 175 | } 176 | if (read_id->nReadPos == m_nDataSize) 177 | read_id->nReadPos = 0; 178 | 179 | if (read_id->nReadPos > m_nDataSize) { 180 | sls_log(SLS_LOG_WARNING, "[%p]CSLSRecycleArray::get, read_id->nReadPos=%d, but m_nDataSize=%d.", 181 | this, read_id->nReadPos, m_nDataSize); 182 | read_id->nReadPos = 0; 183 | } 184 | read_id->nDataCount = m_nDataCount ; 185 | sls_log(SLS_LOG_TRACE, "[%p]CSLSRecycleArray::get, copy_data_lens=%d.", 186 | this, copy_data_len); 187 | return copy_data_len; 188 | } 189 | 190 | int64_t CSLSRecycleArray::get_last_read_time() 191 | { 192 | return m_last_read_time; 193 | } 194 | 195 | 196 | 197 | -------------------------------------------------------------------------------- /slscore/SLSRecycleArray.hpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #ifndef _SLSRecycleArray_INCLUDE_ 27 | #define _SLSRecycleArray_INCLUDE_ 28 | 29 | #include 30 | #include 31 | 32 | #include "common.hpp" 33 | #include "SLSLock.hpp" 34 | 35 | struct SLSRecycleArrayID 36 | { 37 | int nReadPos; 38 | int nDataCount; 39 | bool bFirst; 40 | }; 41 | 42 | 43 | /** 44 | * CSLSRecycleArray 45 | */ 46 | class CSLSRecycleArray 47 | { 48 | public : 49 | CSLSRecycleArray(); 50 | ~CSLSRecycleArray(); 51 | 52 | public : 53 | int put(char *data, int len); 54 | int get(char *dst, int size, SLSRecycleArrayID *read_id, int aligned=0); 55 | 56 | void setSize(int n); 57 | int count(); 58 | 59 | int64_t get_last_read_time(); 60 | private: 61 | char *m_arrayData; 62 | int m_nDataSize; 63 | int m_nDataCount; 64 | int m_nWritePos; 65 | int64_t m_last_read_time; 66 | 67 | 68 | CSLSRWLock m_rwclock; 69 | 70 | 71 | }; 72 | 73 | 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /slscore/SLSRelay.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #include 27 | #include 28 | 29 | 30 | #include "SLSRelay.hpp" 31 | #include "SLSLog.hpp" 32 | #include "SLSRelayManager.hpp" 33 | 34 | /** 35 | * relay conf 36 | */ 37 | SLS_CONF_DYNAMIC_IMPLEMENT(relay) 38 | 39 | /** 40 | * CSLSRelay class implementation 41 | */ 42 | 43 | CSLSRelay::CSLSRelay() 44 | { 45 | m_is_write = 0; 46 | memset(m_url, 0, URL_MAX_LEN); 47 | memset(m_server_ip, 0, IP_MAX_LEN); 48 | 49 | m_server_port = 0; 50 | m_map_publisher = NULL; 51 | m_relay_manager = NULL; 52 | m_need_reconnect = true; 53 | 54 | sprintf(m_role_name, "relay"); 55 | } 56 | 57 | CSLSRelay::~CSLSRelay() 58 | { 59 | //release 60 | } 61 | 62 | int CSLSRelay::uninit() 63 | { 64 | // for reconnect 65 | if (NULL != m_relay_manager) { 66 | ((CSLSRelayManager*)m_relay_manager)->add_reconnect_stream(m_url); 67 | sls_log(SLS_LOG_INFO, "[%p]CSLSRelay::uninit, add_reconnect_stream, m_url=%s.", 68 | this, m_url); 69 | } 70 | 71 | return CSLSRole::uninit(); 72 | } 73 | 74 | void CSLSRelay::set_map_publisher(CSLSMapPublisher *map_publisher) 75 | { 76 | m_map_publisher = map_publisher; 77 | } 78 | 79 | void CSLSRelay::set_relay_manager(void *relay_manager) 80 | { 81 | m_relay_manager = relay_manager; 82 | } 83 | 84 | void *CSLSRelay::get_relay_manager() 85 | { 86 | return m_relay_manager; 87 | } 88 | 89 | int CSLSRelay::parse_url(char* url, char *host_name, int& port, char * streamid) 90 | { 91 | // 92 | if (strlen(url) == 0) { 93 | sls_log(SLS_LOG_INFO, "[%p]CSLSRelay::parse_url='%s', url must like 'srt://hostname:port?streamid=your_stream_id' or 'srt://hostname:port/app/stream_name'.", 94 | this, url); 95 | return SLS_ERROR; 96 | } 97 | sprintf(m_url, "%s", url); 98 | 99 | char * p = url; 100 | //protocal 101 | p = strchr(url, ':'); 102 | if (!p) { 103 | sls_log(SLS_LOG_INFO, "[%p]CSLSRelay::parse_url, no ':', url='%s', url must like 'srt://hostname:port?streamid=your_stream_id' or 'srt://hostname:port/app/stream_name'.", 104 | this, m_url); 105 | return SLS_ERROR; 106 | } 107 | p[0] = 0x00; 108 | if (strcmp(url, "srt") != 0) { 109 | sls_log(SLS_LOG_INFO, "[%p]CSLSRelay::parse_url, not 'srt' prefix, url='%s', url must like 'srt://hostname:port?streamid=your_stream_id' or 'srt://hostname:port/app/stream_name'.", 110 | this, m_url); 111 | return SLS_ERROR; 112 | } 113 | p += 3;//skip 'srt://' 114 | 115 | //hostname:port 116 | char * p_tmp = strchr(p, ':'); 117 | if (p_tmp) { 118 | p_tmp[0] = 0x00; 119 | strcpy(host_name, p); 120 | p = p_tmp + 1; 121 | } 122 | else { 123 | sls_log(SLS_LOG_INFO, "[%p]CSLSRelay::parse_url, not 'hostname:port', url='%s', url must like 'srt://hostname:port?streamid=your_stream_id' or 'srt://hostname:port/app/stream_name'.", 124 | this, m_url); 125 | return SLS_ERROR; 126 | } 127 | 128 | //hostname 129 | bool b_streamid = false; 130 | p_tmp = strchr(p, '?'); 131 | if (!p_tmp) { 132 | sls_log(SLS_LOG_INFO, "[%p]CSLSRelay::parse_url='%s', no '?' param, come on.", 133 | this, m_url); 134 | p_tmp = strchr(p, '/');//app 135 | if (!p_tmp) {//app 136 | sls_log(SLS_LOG_INFO, "[%p]CSLSRelay::parse_url, url='%s', url must like 'srt://hostname:port?streamid=your_stream_id' or 'srt://hostname:port/app/stream_name'.", 137 | this, m_url); 138 | return SLS_ERROR; 139 | } 140 | p_tmp ++; 141 | p_tmp = strchr(p_tmp, '/');//stream 142 | if (!p_tmp) { 143 | sls_log(SLS_LOG_INFO, "[%p]CSLSRelay::parse_url, url='%s', url must like 'srt://hostname:port?streamid=your_stream_id' or 'srt://hostname:port/app/stream_name'.", 144 | this, m_url); 145 | return SLS_ERROR; 146 | } 147 | p_tmp ++; 148 | if (strlen(p_tmp)==0) { 149 | sls_log(SLS_LOG_INFO, "[%p]CSLSRelay::parse_url, url='%s', url must like 'srt://hostname:port?streamid=your_stream_id' or 'srt://hostname:port/app/stream_name'.", 150 | this, m_url); 151 | return SLS_ERROR; 152 | } 153 | p_tmp ++; 154 | p_tmp = strchr(p_tmp, '/');//redundant 155 | if (p_tmp) { 156 | sls_log(SLS_LOG_INFO, "[%p]CSLSRelay::parse_url, url='%s', url must like 'srt://hostname:port?streamid=your_stream_id' or 'srt://hostname:port/app/stream_name'.", 157 | this, m_url); 158 | return SLS_ERROR; 159 | } 160 | }else{ 161 | b_streamid = true; 162 | } 163 | 164 | if (b_streamid) { 165 | p_tmp[0] = 0; 166 | port = atoi(p); 167 | p = p_tmp + 1; 168 | //streamid 169 | p_tmp = strchr(p, '='); 170 | if (!p) { 171 | sls_log(SLS_LOG_INFO, "[%p]CSLSRelay::parse_url='%s', no 'stream=', url must like 'hostname:port?streamid=your_stream_id'.", this, url); 172 | return SLS_ERROR; 173 | } 174 | p_tmp[0] = 0; 175 | if (strcmp(p, "streamid") != 0) { 176 | sls_log(SLS_LOG_INFO, "[%p]CSLSRelay::parse_url='%s', no 'stream', url must like 'hostname:port?streamid=your_stream_id'.", this, url); 177 | return SLS_ERROR; 178 | } 179 | p = p_tmp + 1; 180 | strcpy(streamid, p); 181 | } else { 182 | p_tmp = m_url + strlen("srt://"); 183 | p_tmp = strchr(p, '/'); 184 | sprintf(streamid, "%s%s", host_name, p_tmp); 185 | } 186 | return SLS_OK; 187 | 188 | } 189 | 190 | int CSLSRelay::open(const char * srt_url) { 191 | 192 | int yes = 1; 193 | int no = 0; 194 | char host_name[128] = "192.168.31.56";//test 195 | char server_ip[128] = ""; 196 | int server_port = 8080; 197 | char streamid[1024] = "uplive.sls.net/live/1234";//test 198 | char url[1024] = {0}; 199 | int latency = 10; 200 | 201 | strcpy(m_url, srt_url); 202 | strcpy(url, srt_url); 203 | 204 | //init listener 205 | if (NULL != m_srt) 206 | { 207 | sls_log(SLS_LOG_ERROR, "[%p]CSLSRelay::open, failure, url='%s', m_srt = %p, not NULL.", this, url, m_srt); 208 | return SLS_ERROR; 209 | } 210 | 211 | //parse url 212 | if (SLS_OK != parse_url(url, host_name, server_port, streamid)){ 213 | return SLS_ERROR; 214 | } 215 | sls_log(SLS_LOG_INFO, "[%p]CSLSRelay::open, parse_url ok, url='%s'.", this, m_url); 216 | 217 | if (strlen(streamid) == 0) 218 | { 219 | sls_log(SLS_LOG_ERROR, "[%p]CSLSRelay::open, url='%s', no 'stream', url must like 'hostname:port?streamid=your_stream_id'.", this, m_url); 220 | return SLS_ERROR; 221 | } 222 | 223 | SRTSOCKET fd = srt_socket(AF_INET, SOCK_DGRAM, 0); 224 | 225 | int status = srt_setsockopt(fd, 0, SRTO_SNDSYN, &no, sizeof no); // for async write 226 | if (status == SRT_ERROR) { 227 | sls_log(SLS_LOG_ERROR, "[%p]CSLSRelay::open, srt_setsockopt SRTO_SNDSYN failure. err=%s.", this, srt_getlasterror_str()); 228 | return SLS_ERROR; 229 | } 230 | 231 | status = srt_setsockopt(fd, 0, SRTO_RCVSYN, &no, sizeof no); // for async read 232 | if (status == SRT_ERROR) { 233 | sls_log(SLS_LOG_ERROR, "[%p]CSLSRelay::open, srt_setsockopt SRTO_SNDSYN failure. err=%s.", this, srt_getlasterror_str()); 234 | return SLS_ERROR; 235 | } 236 | 237 | // srt_setsockflag(fd, SRTO_SENDER, &m_is_write, sizeof m_is_write); 238 | /* 239 | status = srt_setsockopt(fd, 0, SRTO_TSBPDMODE, &yes, sizeof yes); // 240 | if (status == SRT_ERROR) { 241 | sls_log(SLS_LOG_ERROR, "[%p]CSLSRelay::open, srt_setsockopt SRTO_TSBPDMODE failure. err=%s.", this, srt_getlasterror_str()); 242 | return SLS_ERROR; 243 | } 244 | /* 245 | SRT_TRANSTYPE tt = SRTT_LIVE; 246 | status = srt_setsockopt(fd, 0, SRTO_TRANSTYPE, &tt, sizeof tt); 247 | if (status == SRT_ERROR) { 248 | sls_log(SLS_LOG_ERROR, "[%p]CSLSRelay::open, srt_setsockopt SRTO_TRANSTYPE failure. err=%s.", this, srt_getlasterror_str()); 249 | return SLS_ERROR; 250 | } 251 | */ 252 | 253 | if (srt_setsockopt(fd, 0, SRTO_STREAMID, streamid, strlen(streamid)) < 0) { 254 | sls_log(SLS_LOG_ERROR, "[%p]CSLSRelay::open, srt_setsockopt SRTO_STREAMID failure. err=%s.", this, srt_getlasterror_str()); 255 | return SLS_ERROR; 256 | } 257 | 258 | struct sockaddr_in sa; 259 | memset(&sa, 0, sizeof sa); 260 | sa.sin_family = AF_INET; 261 | sa.sin_port = htons(server_port); 262 | 263 | sls_gethostbyname(host_name, server_ip); 264 | if (inet_pton(AF_INET, server_ip, &sa.sin_addr) != 1) { 265 | sls_log(SLS_LOG_ERROR, "[%p]CSLSRelay::open, inet_pton failure. server_ip=%s, server_port=%d.", this, server_ip, server_port); 266 | return SLS_ERROR; 267 | } 268 | 269 | struct sockaddr *psa = (struct sockaddr *) &sa; 270 | status = srt_connect(fd, psa, sizeof sa); 271 | if (status == SRT_ERROR) { 272 | sls_log(SLS_LOG_ERROR, "[%p]CSLSRelay::open, srt_connect failure. server_ip=%s, server_port=%d.", this, server_ip, server_port); 273 | return SLS_ERROR; 274 | } 275 | m_srt = new CSLSSrt(); 276 | m_srt->libsrt_set_fd(fd); 277 | strcpy(m_server_ip, server_ip); 278 | m_server_port = server_port; 279 | return status; 280 | } 281 | 282 | int CSLSRelay::close() 283 | { 284 | int ret = SLS_OK; 285 | if (m_srt) { 286 | sls_log(SLS_LOG_INFO, "[%p]CSLSRelay::close, ok, url='%s'.", this, m_url); 287 | ret = m_srt->libsrt_close(); 288 | delete m_srt; 289 | m_srt = NULL; 290 | } 291 | return ret; 292 | } 293 | 294 | char *CSLSRelay::get_url() 295 | { 296 | return m_url; 297 | } 298 | 299 | int CSLSRelay::get_peer_info(char *peer_name, int &peer_port) 300 | { 301 | strcpy(peer_name, m_server_ip); 302 | peer_port = m_server_port; 303 | return SLS_OK; 304 | } 305 | 306 | int CSLSRelay::get_stat_base(char *stat_base) 307 | { 308 | return SLS_OK; 309 | } 310 | 311 | -------------------------------------------------------------------------------- /slscore/SLSRelay.hpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #ifndef _SLSRelay_INCLUDE_ 27 | #define _SLSRelay_INCLUDE_ 28 | 29 | #include 30 | 31 | #include "SLSRole.hpp" 32 | #include "SLSMapPublisher.hpp" 33 | 34 | /** 35 | * sls_conf_relay_t 36 | */ 37 | 38 | SLS_CONF_DYNAMIC_DECLARE_BEGIN(relay) 39 | char type[32]; 40 | char mode[32]; 41 | char upstreams[1024]; 42 | int reconnect_interval; 43 | int idle_streams_timeout; 44 | SLS_CONF_DYNAMIC_DECLARE_END 45 | 46 | 47 | /** 48 | * relay cmd declare 49 | */ 50 | 51 | SLS_CONF_CMD_DYNAMIC_DECLARE_BEGIN(relay) 52 | SLS_SET_CONF(relay, string, type, "pull, push", 1, 31), 53 | SLS_SET_CONF(relay, string, mode, "relay mode.", 1, 31), 54 | SLS_SET_CONF(relay, string, upstreams, "upstreams", 1, 1023), 55 | SLS_SET_CONF(relay, int, reconnect_interval, "reconnect interval, unit s", 1, 3600), 56 | SLS_SET_CONF(relay, int, idle_streams_timeout, "idle streams timeout, unit s", -1, 3600), 57 | 58 | SLS_CONF_CMD_DYNAMIC_DECLARE_END 59 | 60 | 61 | enum SLS_PULL_MODE { 62 | SLS_PM_LOOP = 0, 63 | SLS_PM_HASH = 1, 64 | SLS_PM_ALL = 2, 65 | }; 66 | 67 | /** 68 | * CSLSRelay 69 | */ 70 | class CSLSRelay: public CSLSRole 71 | { 72 | public : 73 | CSLSRelay(); 74 | virtual ~CSLSRelay(); 75 | 76 | virtual int uninit(); 77 | 78 | void set_map_publisher(CSLSMapPublisher *publisher); 79 | void set_relay_manager(void *relay_manager); 80 | void *get_relay_manager(); 81 | char *get_url(); 82 | 83 | int open(const char *url); 84 | virtual int close(); 85 | virtual int get_peer_info(char *peer_name, int &peer_port); 86 | virtual int get_stat_base(char *stat_base) ; 87 | protected: 88 | char m_url[URL_MAX_LEN]; 89 | char m_upstream[URL_MAX_LEN]; 90 | char m_server_ip[IP_MAX_LEN]; 91 | int m_server_port; 92 | 93 | CSLSMapPublisher *m_map_publisher; 94 | void *m_relay_manager; 95 | 96 | int parse_url(char* url, char * ip, int& port, char * streamid); 97 | 98 | }; 99 | 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /slscore/SLSRelayManager.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #include 27 | #include 28 | 29 | #include "common.hpp" 30 | #include "SLSRelayManager.hpp" 31 | #include "SLSLog.hpp" 32 | 33 | 34 | /** 35 | * CSLSRelayManager class implementation 36 | */ 37 | CSLSRelayManager::CSLSRelayManager() 38 | { 39 | m_reconnect_begin_tm = 0; 40 | m_map_publisher = NULL; 41 | m_map_data = NULL; 42 | m_role_list = NULL; 43 | m_sri = NULL; 44 | m_listen_port = 0; 45 | 46 | memset(m_app_uplive, 0, sizeof(m_app_uplive)); 47 | memset(m_stream_name, 0, sizeof(m_stream_name)); 48 | 49 | } 50 | 51 | CSLSRelayManager::~CSLSRelayManager() 52 | { 53 | } 54 | 55 | void CSLSRelayManager::set_map_publisher(CSLSMapPublisher *map_publisher) 56 | { 57 | m_map_publisher = map_publisher; 58 | } 59 | 60 | void CSLSRelayManager::set_map_data(CSLSMapData *map_data) 61 | { 62 | m_map_data = map_data; 63 | } 64 | 65 | void CSLSRelayManager::set_role_list(CSLSRoleList *role_list) 66 | { 67 | m_role_list = role_list; 68 | } 69 | 70 | void CSLSRelayManager::set_relay_conf(SLS_RELAY_INFO *sri) 71 | { 72 | m_sri = sri; 73 | } 74 | 75 | void CSLSRelayManager::set_relay_info(const char *app_uplive, const char *stream_name) 76 | { 77 | strcpy(m_app_uplive, app_uplive); 78 | strcpy(m_stream_name, stream_name); 79 | } 80 | 81 | void CSLSRelayManager::set_listen_port(int port) 82 | { 83 | m_listen_port = port; 84 | } 85 | 86 | int CSLSRelayManager::connect(const char *url) 87 | { 88 | int ret = SLS_ERROR; 89 | if (url == NULL || strlen(url) == 0) { 90 | sls_log(SLS_LOG_INFO, "[%p]CSLSManager::connect, failed, url=%s.", url?url:"null"); 91 | return ret; 92 | } 93 | 94 | CSLSRelay * cur_relay = create_relay();//new relay; 95 | cur_relay->init(); 96 | ret = cur_relay->open(url); 97 | if (SLS_OK == ret) { 98 | cur_relay->set_idle_streams_timeout(m_sri->m_idle_streams_timeout); 99 | 100 | //set stat info 101 | char tmp[URL_MAX_LEN] = {0}; 102 | char stat_base[URL_MAX_LEN] = {0}; 103 | char cur_time[STR_DATE_TIME_LEN] = {0}; 104 | sls_gettime_default_string(cur_time); 105 | char relay_peer_name[IP_MAX_LEN] = {0}; 106 | int relay_peer_port = 0; 107 | cur_relay->get_peer_info(relay_peer_name, relay_peer_port); 108 | cur_relay->get_stat_base(stat_base); 109 | sprintf(tmp, stat_base, 110 | m_listen_port, cur_relay->get_role_name(), m_app_uplive, m_stream_name, url, relay_peer_name, relay_peer_port, cur_time); 111 | std::string stat_info = std::string(tmp); 112 | cur_relay->set_stat_info_base(stat_info); 113 | 114 | ret = set_relay_param(cur_relay); 115 | if (SLS_OK != ret) { 116 | cur_relay->uninit(); 117 | delete cur_relay; 118 | cur_relay = NULL; 119 | } 120 | return ret; 121 | } else { 122 | cur_relay->uninit(); 123 | delete cur_relay ; 124 | cur_relay = NULL; 125 | } 126 | return ret; 127 | } 128 | 129 | int CSLSRelayManager::connect_hash() 130 | { 131 | //make hash to hostnames by stream_name 132 | std::string url = get_hash_url(); 133 | char szURL[1024] = {0}; 134 | const char *szTmp = url.c_str(); 135 | sprintf(szURL, "srt://%s/%s", szTmp, m_stream_name); 136 | int ret = connect(szURL); 137 | if (SLS_OK != ret) { 138 | sls_log(SLS_LOG_INFO, "[%p]CSLSRelayManager::connect_hash, faild, connect szURL=%s, m_stream_name=%s.", 139 | this, szURL, m_stream_name); 140 | } else { 141 | sls_log(SLS_LOG_INFO, "[%p]CSLSRelayManager::connect_hash, ok, connect szURL=%s, m_stream_name=%s.", 142 | this, szURL, m_stream_name); 143 | } 144 | return ret; 145 | } 146 | 147 | 148 | std::string CSLSRelayManager::get_hash_url() 149 | { 150 | if (NULL == m_sri) { 151 | return ""; 152 | } 153 | uint32_t key = sls_hash_key(m_stream_name, strlen(m_stream_name)); 154 | uint32_t index = key % m_sri->m_upstreams.size(); 155 | return m_sri->m_upstreams[index]; 156 | 157 | } 158 | -------------------------------------------------------------------------------- /slscore/SLSRelayManager.hpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #ifndef _SLSRelayManager_INCLUDE_ 27 | #define _SLSRelayManager_INCLUDE_ 28 | 29 | #include 30 | #include 31 | 32 | #include "SLSRelay.hpp" 33 | #include "SLSMapPublisher.hpp" 34 | #include "conf.hpp" 35 | #include "SLSRoleList.hpp" 36 | 37 | typedef struct SLS_RELAY_INFO { 38 | std::vector m_upstreams; 39 | char m_type[32]; 40 | int m_mode; 41 | int m_reconnect_interval;//unit: s 42 | int m_idle_streams_timeout;//unit: s 43 | }; 44 | 45 | /** 46 | * CSLSRelayManager 47 | */ 48 | class CSLSRelayManager 49 | { 50 | public : 51 | CSLSRelayManager(); 52 | virtual ~CSLSRelayManager(); 53 | 54 | virtual int start() = 0; 55 | virtual int reconnect(int64_t cur_tm_ms) = 0; 56 | 57 | virtual int add_reconnect_stream(char* relay_url) = 0; 58 | 59 | void set_map_publisher(CSLSMapPublisher *publisher); 60 | void set_map_data(CSLSMapData *map_data); 61 | void set_role_list(CSLSRoleList *role_list); 62 | 63 | void set_relay_conf(SLS_RELAY_INFO *sri); 64 | void set_relay_info(const char *app_uplive, const char *stream_name); 65 | void set_listen_port(int port); 66 | 67 | protected: 68 | CSLSMapPublisher *m_map_publisher ; 69 | CSLSMapData *m_map_data ; 70 | CSLSRoleList *m_role_list; 71 | SLS_RELAY_INFO *m_sri; 72 | int64_t m_reconnect_begin_tm;//unit: ms 73 | int m_listen_port; 74 | 75 | char m_app_uplive[1024]; 76 | char m_stream_name[1024]; 77 | 78 | int connect(const char *url); 79 | int connect_hash(); 80 | 81 | virtual CSLSRelay *create_relay() = 0; 82 | std::string get_hash_url(); 83 | 84 | virtual int set_relay_param(CSLSRelay *relay) = 0; 85 | 86 | }; 87 | 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /slscore/SLSRole.hpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #ifndef _SLSRole_INCLUDE_ 27 | #define _SLSRole_INCLUDE_ 28 | 29 | #include 30 | 31 | 32 | #include "SLSRole.hpp" 33 | #include "SLSSrt.hpp" 34 | #include "SLSMapData.hpp" 35 | #include "conf.hpp" 36 | #include "SLSLock.hpp" 37 | #include "common.hpp" 38 | #include "HttpClient.hpp" 39 | 40 | 41 | enum SLS_ROLE_STATE { 42 | SLS_RS_UNINIT = 0, 43 | SLS_RS_INITED = 1, 44 | SLS_RS_INVALID = 2, 45 | }; 46 | 47 | const int DATA_BUFF_SIZE = 100 * 1316; 48 | const int UNLIMITED_TIMEOUT = -1; 49 | /** 50 | * CSLSRole , the base of player, publisher and listener 51 | */ 52 | class CSLSRole 53 | { 54 | public : 55 | CSLSRole(); 56 | virtual ~CSLSRole(); 57 | 58 | 59 | virtual int init(); 60 | virtual int uninit(); 61 | virtual int handler(); 62 | 63 | int open(char *url); 64 | int close(); 65 | 66 | int get_fd(); 67 | int set_eid(int eid); 68 | bool is_write(){return m_is_write;}; 69 | 70 | int set_srt(CSLSSrt *srt); 71 | int invalid_srt(); 72 | 73 | int write(const char *buf, int size); 74 | 75 | int add_to_epoll(int eid); 76 | int remove_from_epoll(); 77 | int get_state(int64_t cur_time_microsec = 0); 78 | int get_sock_state(); 79 | char * get_role_name(); 80 | 81 | void set_conf(sls_conf_base_t *conf); 82 | void set_map_data(char *map_key, CSLSMapData *map_data); 83 | 84 | void set_idle_streams_timeout(int timeout); 85 | bool check_idle_streams_duration(int64_t cur_time_ms = 0); 86 | 87 | char * get_streamid(); 88 | bool is_reconnect(); 89 | 90 | void set_stat_info_base(std::string &v); 91 | virtual std::string get_stat_info(); 92 | void update_stat_info(); 93 | virtual int get_peer_info(char *peer_name, int &peer_port); 94 | 95 | void set_http_url(const char *http_url); 96 | int on_connect(); 97 | int on_close(); 98 | int get_statistics(SRT_TRACEBSTATS *currentStats, int clear); 99 | int get_bitrate(); 100 | int get_uptime(); 101 | int check_http_client(); 102 | int check_http_passed(); 103 | 104 | void set_record_hls_path(const char *hls_path); 105 | protected: 106 | CSLSSrt *m_srt; 107 | bool m_is_write;//listener: 0, publisher: 0, player: 1 108 | int64_t m_stat_start_time; 109 | int64_t m_invalid_begin_tm;// 110 | int64_t m_stat_bitrate_last_tm;// 111 | int m_stat_bitrate_interval ;//ms 112 | int m_stat_bitrate_datacount ; 113 | int m_kbitrate;//kb 114 | int m_idle_streams_timeout;//unit: s, -1: unlimited 115 | int m_latency;//ms 116 | 117 | int m_state; 118 | int m_back_log;//maximum number of connections at the same time 119 | int m_port; 120 | char m_peer_ip[IP_MAX_LEN]; 121 | int m_peer_port; 122 | char m_role_name[STR_MAX_LEN]; 123 | char m_streamid[URL_MAX_LEN]; 124 | char m_http_url[URL_MAX_LEN]; 125 | bool m_http_passed; 126 | 127 | sls_conf_base_t *m_conf; 128 | CSLSMapData *m_map_data; 129 | char m_map_data_key[URL_MAX_LEN]; 130 | SLSRecycleArrayID m_map_data_id; 131 | 132 | char m_data[DATA_BUFF_SIZE]; 133 | int m_data_len; 134 | int m_data_pos; 135 | bool m_need_reconnect; 136 | std::string m_stat_info_base; 137 | CHttpClient *m_http_client; 138 | 139 | char m_record_hls[SHORT_STR_MAX_LEN]; 140 | int m_record_hls_ts_fd ; 141 | char m_record_hls_ts_filename[URL_MAX_LEN]; 142 | int m_record_hls_vod_fd ; 143 | char m_record_hls_vod_filename[URL_MAX_LEN]; 144 | char m_record_hls_path[URL_MAX_LEN]; 145 | int64_t m_record_hls_begin_tm_ms ; 146 | int m_record_hls_segment_duration; 147 | float m_record_hls_target_duration; 148 | 149 | int handler_write_data(); 150 | int handler_read_data(int64_t *last_read_time=NULL); 151 | void record_data2hls(char *data, int len); 152 | void check_hls_file(); 153 | void close_hls_file(); 154 | private: 155 | 156 | }; 157 | 158 | 159 | #endif 160 | -------------------------------------------------------------------------------- /slscore/SLSRoleList.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #include 27 | #include 28 | 29 | 30 | #include "SLSRoleList.hpp" 31 | #include "SLSLog.hpp" 32 | #include "SLSLock.hpp" 33 | 34 | /** 35 | * CSLSRoleList class implementation 36 | */ 37 | 38 | CSLSRoleList::CSLSRoleList() 39 | { 40 | } 41 | CSLSRoleList::~CSLSRoleList() 42 | { 43 | } 44 | 45 | int CSLSRoleList::push(CSLSRole * role) 46 | { 47 | if (role) { 48 | CSLSLock lock(&m_mutex); 49 | m_list_role.push_back(role); 50 | } 51 | return 0; 52 | } 53 | 54 | CSLSRole * CSLSRoleList::pop() 55 | { 56 | CSLSLock lock(&m_mutex); 57 | CSLSRole * role = NULL; 58 | if (!m_list_role.empty()) { 59 | role = m_list_role.front(); 60 | m_list_role.pop_front(); 61 | } 62 | return role; 63 | } 64 | 65 | void CSLSRoleList::erase() 66 | { 67 | CSLSLock lock(&m_mutex); 68 | sls_log(SLS_LOG_TRACE, "[%p]CSLSRoleList::erase, list.count=%d", this, m_list_role.size()); 69 | std::list::iterator it_erase; 70 | for (std::list::iterator it = m_list_role.begin(); it != m_list_role.end();) 71 | { 72 | CSLSRole * role = *it; 73 | if (role) { 74 | role->uninit(); 75 | delete role; 76 | } 77 | it ++; 78 | } 79 | m_list_role.clear(); 80 | } 81 | 82 | int CSLSRoleList::size() 83 | { 84 | CSLSLock lock(&m_mutex); 85 | return m_list_role.size(); 86 | } 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /slscore/SLSRoleList.hpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #ifndef _SLSRoleList_INCLUDE_ 27 | #define _SLSRoleList_INCLUDE_ 28 | 29 | #include 30 | 31 | #include "SLSRole.hpp" 32 | #include "SLSLock.hpp" 33 | 34 | /** 35 | * CSLSRoleList 36 | */ 37 | class CSLSRoleList 38 | { 39 | public : 40 | CSLSRoleList(); 41 | ~CSLSRoleList(); 42 | 43 | int push(CSLSRole *role); 44 | CSLSRole *pop(); 45 | void erase(); 46 | int size(); 47 | 48 | protected: 49 | 50 | private: 51 | std::list m_list_role; 52 | 53 | CSLSMutex m_mutex; 54 | }; 55 | 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /slscore/SLSSrt.hpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #ifndef _SLSRrt_INCLUDE_ 27 | #define _SLSRrt_INCLUDE_ 28 | 29 | #include 30 | 31 | enum SRTMode { 32 | SRT_MODE_CALLER = 0, 33 | SRT_MODE_LISTENER = 1, 34 | SRT_MODE_RENDEZVOUS = 2 35 | }; 36 | 37 | typedef struct SRTContext { 38 | SRTSOCKET fd; 39 | int eid; 40 | int flag; 41 | int port; 42 | char hostname[1024]; 43 | int reuse; 44 | int backlog; 45 | 46 | int64_t rw_timeout; 47 | int64_t listen_timeout; 48 | int recv_buffer_size; 49 | int send_buffer_size; 50 | 51 | int64_t maxbw; 52 | int pbkeylen; 53 | char *passphrase; 54 | int mss; 55 | int ffs; 56 | int ipttl; 57 | int iptos; 58 | int64_t inputbw; 59 | int oheadbw; 60 | int64_t latency; 61 | int tlpktdrop; 62 | int nakreport; 63 | int64_t connect_timeout; 64 | int payload_size; 65 | int64_t rcvlatency; 66 | int64_t peerlatency; 67 | enum SRTMode mode; 68 | int sndbuf; 69 | int rcvbuf; 70 | int lossmaxttl; 71 | int minversion; 72 | char *streamid; 73 | char *smoother; 74 | int messageapi; 75 | SRT_TRANSTYPE transtype; 76 | 77 | double mbpsBandwidth; 78 | double msRTT; 79 | } SRTContext; 80 | 81 | /** 82 | * CSLSSrt ,functions of srt 83 | */ 84 | class CSLSSrt 85 | { 86 | public : 87 | CSLSSrt(); 88 | ~CSLSSrt(); 89 | 90 | static int libsrt_init(); 91 | static int libsrt_uninit(); 92 | static int libsrt_epoll_create(); 93 | static void libsrt_epoll_release(int eid); 94 | 95 | void libsrt_set_context(SRTContext *sc); 96 | 97 | int libsrt_setup(int port); 98 | int libsrt_close(); 99 | 100 | int libsrt_listen(int backlog); 101 | int libsrt_set_listen_callback(srt_listen_callback_fn * listen_callback_fn); 102 | int libsrt_accept(); 103 | 104 | int libsrt_get_fd(); 105 | int libsrt_set_fd(int fd); 106 | 107 | int libsrt_set_eid(int eid); 108 | 109 | int libsrt_read(char *buf, int size); 110 | int libsrt_write(const char *buf, int size); 111 | 112 | int libsrt_socket_nonblock(int enable); 113 | 114 | int libsrt_getsockopt(SRT_SOCKOPT optname, const char * optnamestr, void * optval, int * optlen); 115 | int libsrt_setsockopt(SRT_SOCKOPT optname, const char * optnamestr, const void * optval, int optlen); 116 | 117 | std::map libsrt_parse_sid(char *sid); 118 | 119 | int libsrt_add_to_epoll(int eid, bool write); 120 | int libsrt_remove_from_epoll(); 121 | 122 | int libsrt_getsockstate(); 123 | int libsrt_getpeeraddr(char * peer_name, int& port); 124 | int libsrt_get_statistics(SRT_TRACEBSTATS *currentStats, int clear); 125 | 126 | void libsrt_set_latency(int latency); 127 | 128 | 129 | static int libsrt_neterrno(); 130 | static void libsrt_print_error_info(); 131 | 132 | 133 | protected: 134 | SRTContext m_sc; 135 | char m_peer_name[256];//peer ip addr, such as 172.12.22.14 136 | int m_peer_port ; 137 | 138 | private: 139 | static bool m_inited; 140 | }; 141 | 142 | 143 | #endif 144 | -------------------------------------------------------------------------------- /slscore/SLSSyncClock.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | #include 26 | 27 | #include "SLSSyncClock.hpp" 28 | #include "common.hpp" 29 | 30 | #define TM_JITTER 1000//ms 31 | 32 | CSLSSyncClock::CSLSSyncClock() 33 | { 34 | m_jitter = TM_JITTER; 35 | m_begin_ms_rts = -1; 36 | m_begin_ms_sys = -1; 37 | } 38 | 39 | CSLSSyncClock::~CSLSSyncClock() 40 | { 41 | } 42 | 43 | int CSLSSyncClock::wait(int64_t rts_tm_ms) 44 | { 45 | if (-1 == m_begin_ms_rts) { 46 | m_begin_ms_rts = rts_tm_ms; 47 | m_begin_ms_sys = sls_gettime_ms(); 48 | return SLS_OK; 49 | } 50 | int64_t cur_sys_ms = sls_gettime_ms(); 51 | int64_t sys_passed = cur_sys_ms - m_begin_ms_sys; 52 | int64_t rts_passed = rts_tm_ms - m_begin_ms_rts; 53 | int64_t d = rts_passed - sys_passed; 54 | if (d >= m_jitter || d <= (-1 * m_jitter)) { 55 | //jitter 56 | m_begin_ms_rts = rts_tm_ms; 57 | m_begin_ms_sys = cur_sys_ms; 58 | return SLS_OK; 59 | } 60 | if (d > 0) { 61 | //printf("rts_passed=%lld, sys_passed=%lld, d=%lld\n", rts_passed, sys_passed, d); 62 | msleep(d); 63 | } 64 | return SLS_OK; 65 | } 66 | 67 | void CSLSSyncClock::set_jitter(int v) 68 | { 69 | m_jitter = v; 70 | } 71 | 72 | -------------------------------------------------------------------------------- /slscore/SLSSyncClock.hpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #ifndef _SLSSyncLock_INCLUDE_ 27 | #define _SLSSyncLock_INCLUDE_ 28 | 29 | #include 30 | #include 31 | 32 | /** 33 | * CSLSSyncClock 34 | */ 35 | class CSLSSyncClock 36 | { 37 | public : 38 | CSLSSyncClock(); 39 | ~CSLSSyncClock(); 40 | 41 | int wait(int64_t rts_tm_ms); 42 | void set_jitter(int v); 43 | private: 44 | int64_t m_begin_ms_rts; 45 | int64_t m_begin_ms_sys; 46 | int m_jitter; 47 | 48 | }; 49 | 50 | 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /slscore/SLSThread.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #include 27 | #include 28 | 29 | 30 | #include "SLSThread.hpp" 31 | #include "SLSLog.hpp" 32 | 33 | /** 34 | * CSLSThread class implementation 35 | */ 36 | 37 | CSLSThread::CSLSThread() 38 | { 39 | m_exit = 0; 40 | m_th_id = 0; 41 | } 42 | CSLSThread::~CSLSThread() 43 | { 44 | stop(); 45 | } 46 | 47 | int CSLSThread::start() 48 | { 49 | int ret = 0; 50 | int err; 51 | pthread_t th_id; 52 | 53 | err = pthread_create(&th_id, NULL, thread_func, (void *)this); 54 | if (err != 0) { 55 | sls_log(SLS_LOG_ERROR, "[%p]CSLSThread::start, can't create thread, error: %s\n", this, strerror(err)); 56 | return -1; 57 | } 58 | m_th_id = th_id; 59 | sls_log(SLS_LOG_INFO, "[%p]CSLSThread::start, pthread_create ok, m_th_id=%lld.", this, m_th_id); 60 | 61 | return ret; 62 | 63 | } 64 | int CSLSThread::stop() 65 | { 66 | int ret = 0; 67 | if (0 == m_th_id) { 68 | return ret; 69 | } 70 | sls_log(SLS_LOG_INFO, "[%p]CSLSThread::stop, m_th_id=%lld.", this, m_th_id); 71 | 72 | m_exit = 1; 73 | pthread_join(m_th_id, NULL); 74 | m_th_id = 0; 75 | clear(); 76 | 77 | return ret; 78 | 79 | } 80 | 81 | void CSLSThread::clear() 82 | { 83 | 84 | } 85 | 86 | bool CSLSThread::is_exit() 87 | { 88 | return m_exit == 1; 89 | } 90 | 91 | void * CSLSThread::thread_func(void * arg) 92 | { 93 | CSLSThread *pThis = (CSLSThread *)arg; 94 | if (!pThis) 95 | { 96 | sls_log(SLS_LOG_ERROR, "CSLSThread::thread_func, thread arg is null.\n"); 97 | } 98 | 99 | pThis->work(); 100 | return NULL; 101 | } 102 | 103 | 104 | int CSLSThread::work() 105 | { 106 | int ret = 0; 107 | 108 | return ret; 109 | 110 | } 111 | -------------------------------------------------------------------------------- /slscore/SLSThread.hpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #ifndef _SLSThread_INCLUDE_ 27 | #define _SLSThread_INCLUDE_ 28 | 29 | 30 | #include 31 | 32 | 33 | 34 | /** 35 | * CSLSThread , the base thread class 36 | */ 37 | class CSLSThread 38 | { 39 | public : 40 | CSLSThread(); 41 | ~CSLSThread(); 42 | 43 | int start(); 44 | int stop(); 45 | 46 | bool is_exit(); 47 | 48 | 49 | virtual int work(); 50 | protected: 51 | bool m_exit; 52 | pthread_t m_th_id; 53 | 54 | virtual void clear(); 55 | 56 | private: 57 | static void *thread_func(void *); 58 | 59 | }; 60 | 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /slscore/TCPRole.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2019-2020 Edward.Wu 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 7 | * this software and associated documentation files (the "Software"), to deal in 8 | * the Software without restriction, including without limitation the rights to 9 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 10 | * the Software, and to permit persons to whom the Software is furnished to do so, 11 | * subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include 25 | #include 26 | 27 | #include "TCPRole.hpp" 28 | #include "SLSLog.hpp" 29 | 30 | #define MAX_TCP_SOCK_COUNT 1 31 | 32 | /** 33 | * CTCPRole class implementation 34 | */ 35 | 36 | CTCPRole::CTCPRole() 37 | { 38 | m_fd = 0; 39 | m_port = 0; 40 | m_remote_port = 0; 41 | m_valid = false; 42 | 43 | strcpy(m_remote_host, ""); 44 | sprintf(m_role_name, "tcp_role"); 45 | } 46 | CTCPRole::~CTCPRole() 47 | { 48 | close(); 49 | } 50 | 51 | int CTCPRole::handler(DATA_PARAM *p) 52 | { 53 | int ret = 0; 54 | //sls_log(SLS_LOG_INFO, "CTCPRole::handler()"); 55 | return ret; 56 | } 57 | 58 | int CTCPRole::write(const char * buf, int size) 59 | { 60 | int len = 0; 61 | len = send(m_fd, buf, size, 0); 62 | if (0 >= len) { 63 | sls_log(SLS_LOG_INFO, "[%p]CTCPRole::read, len=%d, errno=%d, err='%s'", 64 | this, len, errno, strerror(errno)); 65 | 66 | } 67 | return len; 68 | } 69 | 70 | int CTCPRole::read(char * buf, int size) 71 | { 72 | int len = 0; 73 | len = recv(m_fd, buf, size, 0); 74 | if (len <= 0){ 75 | sls_log(SLS_LOG_TRACE, "[%p]CTCPRole::read, len=%d, errno=%d, err='%s'.", 76 | this, len, errno, strerror(errno)); 77 | if (errno != EAGAIN ) { 78 | sls_log(SLS_LOG_INFO, "[%p]CTCPRole::read, invalid tcp.", 79 | this); 80 | m_valid = false; 81 | } 82 | } 83 | return len; 84 | } 85 | 86 | int CTCPRole::open(char *host, int port) 87 | { 88 | if (SLS_OK != setup()) 89 | { 90 | sls_log(SLS_LOG_ERROR, "[%p]CTCPRole::open setup failure, host='%s', port==%d.", this, host, port); 91 | return SLS_ERROR; 92 | } 93 | if (SLS_OK != connect(host, port)) 94 | { 95 | sls_log(SLS_LOG_ERROR, "[%p]CTCPRole::open setup connect failure, host='%s', port==%d.", this, host, port); 96 | return SLS_ERROR; 97 | } 98 | m_valid = true; 99 | return SLS_OK; 100 | } 101 | 102 | int CTCPRole::connect(char *host, int port) 103 | { 104 | if (m_fd <= 0) { 105 | sls_log(SLS_LOG_ERROR, "[%p]CTCPRole::connect, m_fd=%d, cant't setup, host='%s', port==%d.", this, m_fd, host, port); 106 | return SLS_ERROR; 107 | } 108 | int ret = SLS_ERROR; 109 | 110 | //must be nonblock, otherwise, if the host is wrong, connect will be blocked. 111 | ret = set_nonblock(); 112 | if (ret == SLS_ERROR) { 113 | sls_log(SLS_LOG_ERROR, "[%p]CTCPRole::connect, set_nonblock failure, m_fd=%d.", this, m_fd); 114 | return SLS_ERROR; 115 | } 116 | 117 | struct sockaddr_in servaddr; 118 | bzero(&servaddr, sizeof(servaddr)); 119 | servaddr.sin_family = AF_INET; 120 | servaddr.sin_port = htons(port); 121 | //inet_pton(AF_INET, host, &servaddr.sin_addr); 122 | servaddr.sin_addr.s_addr = inet_addr(host); 123 | 124 | ret = ::connect(m_fd, (struct sockaddr *) &servaddr, sizeof(servaddr)); 125 | if ( ret != 0 ) 126 | { 127 | if (errno != EINPROGRESS) 128 | { 129 | sls_log(SLS_LOG_ERROR, "[%p]CTCPRole::connect, failure, m_fd=%d, host=%s, port==%d, errno=%d.", this, m_fd, host, port, errno); 130 | ::close(m_fd); 131 | m_fd = 0; 132 | return SLS_ERROR; 133 | } 134 | } 135 | 136 | sls_log(SLS_LOG_INFO, "[%p]CTCPRole::connect, ok, m_fd=%d, host=%s, port==%d.", this, m_fd, host, port); 137 | strcpy(m_remote_host, host); 138 | m_remote_port = port; 139 | return SLS_OK; 140 | } 141 | 142 | int CTCPRole::open(int port, int backlog) 143 | { 144 | if (SLS_OK != setup()) 145 | { 146 | sls_log(SLS_LOG_ERROR, "[%p]CTCPRole::open setup failure, port==%d.", this, port); 147 | return SLS_ERROR; 148 | } 149 | if (SLS_OK != listen(port, backlog)) 150 | { 151 | sls_log(SLS_LOG_ERROR, "[%p]CTCPRole::open listen failure, port==%d.", this, port); 152 | return SLS_ERROR; 153 | } 154 | m_valid = true; 155 | return SLS_OK; 156 | 157 | } 158 | 159 | int CTCPRole::setup() 160 | { 161 | if (m_fd > 0) { 162 | sls_log(SLS_LOG_ERROR, "[%p]CTCPRole::setup, m_fd=%d, cant't setup.", this, m_fd); 163 | return SLS_ERROR; 164 | } 165 | 166 | m_fd = socket(AF_INET, SOCK_STREAM, 0); 167 | if (m_fd == 0) { 168 | sls_log(SLS_LOG_ERROR, "[%p]CTCPRole::setup, create sock failure.", this); 169 | return SLS_ERROR; 170 | } 171 | sls_log(SLS_LOG_INFO, "[%p]CTCPRole::setup, create sock ok, m_fd=%d.", this, m_fd); 172 | 173 | int yes = 1; 174 | int ret = setsockopt(m_fd, 175 | SOL_SOCKET, SO_REUSEADDR, 176 | (void *)&yes, sizeof(yes)); 177 | if (ret != 0) { 178 | sls_log(SLS_LOG_ERROR, "[%p]CTCPRole::setup, setsockopt reused failure, m_fd=%d.", this, m_fd); 179 | return SLS_ERROR; 180 | } 181 | sls_log(SLS_LOG_INFO, "[%p]CTCPRole::setup, setsockopt reused ok, m_fd=%d.", this, m_fd); 182 | 183 | return SLS_OK; 184 | } 185 | 186 | int CTCPRole::set_nonblock() 187 | { 188 | if (m_fd <= 0) { 189 | sls_log(SLS_LOG_ERROR, "[%p]CTCPRole::set_nonblock, m_fd=%d, cant't setup.", this, m_fd); 190 | return SLS_ERROR; 191 | } 192 | int opts; 193 | opts=fcntl(m_fd, F_GETFL); 194 | if(opts<0) 195 | { 196 | sls_log(SLS_LOG_ERROR, "[%p]CTCPRole::set_nonblock, fcntl failure, m_fd=%d.", this, m_fd); 197 | return SLS_ERROR; 198 | } 199 | opts = opts|O_NONBLOCK; 200 | if(fcntl(m_fd, F_SETFL, opts)<0) 201 | { 202 | sls_log(SLS_LOG_ERROR, "[%p]CTCPRole::set_nonblock, fcntl set O_NONBLOCK failure, m_fd=%d.", this, m_fd); 203 | return SLS_ERROR; 204 | } 205 | sls_log(SLS_LOG_INFO, "[%p]CTCPRole::set_nonblock, set O_NONBLOCK ok, m_fd=%d.", this, m_fd); 206 | return SLS_OK; 207 | } 208 | 209 | int CTCPRole::listen(int port, int backlog) 210 | { 211 | if (m_fd <= 0) { 212 | sls_log(SLS_LOG_ERROR, "[%p]CTCPRole::listen, m_fd=%d, cant't setup.", this, m_fd); 213 | return SLS_ERROR; 214 | } 215 | struct sockaddr_in serverAdd; 216 | struct sockaddr_in clientAdd; 217 | 218 | bzero(&serverAdd, sizeof(serverAdd)); 219 | serverAdd.sin_family = AF_INET; 220 | serverAdd.sin_addr.s_addr = htonl(INADDR_ANY); 221 | serverAdd.sin_port = htons(port); 222 | 223 | socklen_t clientAddrLen; 224 | int ret = bind(m_fd, (struct sockaddr *)&serverAdd, sizeof(serverAdd)); 225 | if (ret < 0) { 226 | sls_log(SLS_LOG_ERROR, "[%p]CTCPRole::listen, bind failure, m_fd=%d, port=%d.", this, m_fd, port); 227 | close(); 228 | return SLS_ERROR; 229 | } 230 | sls_log(SLS_LOG_INFO, "[%p]CTCPRole::listen, bind ok, m_fd=%d, port=%d.", this, m_fd, port); 231 | m_port = port; 232 | 233 | ret = ::listen(m_fd, backlog); 234 | if (ret < 0) { 235 | sls_log(SLS_LOG_ERROR, "[%p]CTCPRole::listen, listen failure, m_fd=%d, port=%d.", this, m_fd, port); 236 | close(); 237 | return SLS_ERROR; 238 | } 239 | sls_log(SLS_LOG_INFO, "[%p]CTCPRole::listen, listen ok, m_fd=%d, port=%d.", this, m_fd, port); 240 | return SLS_OK; 241 | } 242 | 243 | int CTCPRole::close() { 244 | if (m_fd <= 0) { 245 | return SLS_ERROR; 246 | } 247 | sls_log(SLS_LOG_INFO, "[%p]CTCPRole::close ok, m_fd=%d.", this, m_fd); 248 | ::close(m_fd); 249 | m_fd = 0; 250 | m_valid = false; 251 | return SLS_OK; 252 | } 253 | 254 | 255 | char * CTCPRole::get_role_name() 256 | { 257 | return m_role_name; 258 | } 259 | 260 | bool CTCPRole::is_valid() 261 | { 262 | return m_valid; 263 | } 264 | 265 | int CTCPRole::get_fd() 266 | { 267 | return m_fd; 268 | } 269 | 270 | 271 | 272 | 273 | 274 | 275 | -------------------------------------------------------------------------------- /slscore/TCPRole.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2019-2020 Edward.Wu 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 7 | * this software and associated documentation files (the "Software"), to deal in 8 | * the Software without restriction, including without limitation the rights to 9 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 10 | * the Software, and to permit persons to whom the Software is furnished to do so, 11 | * subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef _TCPRole_INCLUDE_ 25 | #define _TCPRole_INCLUDE_ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | #include "conf.hpp" 46 | 47 | typedef struct DATA_PARAM { 48 | bool readable; 49 | bool writable; 50 | }; 51 | /** 52 | * CTCPRole , the base of tcp client 53 | */ 54 | class CTCPRole 55 | { 56 | public : 57 | CTCPRole(); 58 | virtual ~CTCPRole(); 59 | 60 | int open(int port, int backlog); 61 | int open(char *host, int port); 62 | virtual int close(); 63 | 64 | virtual int handler(DATA_PARAM *p); 65 | 66 | int write(const char *buf, int size); 67 | int read(char *buf, int size); 68 | 69 | char *get_role_name(); 70 | int set_nonblock(); 71 | int get_fd(); 72 | 73 | bool is_valid(); 74 | protected: 75 | int m_fd; 76 | int m_port; 77 | char m_role_name[256]; 78 | char m_remote_host[256]; 79 | int m_remote_port; 80 | bool m_valid; 81 | 82 | int setup(); 83 | int listen(int port, int backlog); 84 | int connect(char *host, int port); 85 | 86 | }; 87 | 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /slscore/TSFileTimeReader.hpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #ifndef _TSFileTimeReader_INCLUDE_ 27 | #define _TSFileTimeReader_INCLUDE_ 28 | 29 | #include 30 | 31 | #include "common.hpp" 32 | #include "SLSArray.hpp" 33 | #include "SLSSyncClock.hpp" 34 | 35 | /** 36 | * CTSFileTimeReader 37 | */ 38 | class CTSFileTimeReader 39 | { 40 | public : 41 | CTSFileTimeReader(); 42 | ~CTSFileTimeReader(); 43 | 44 | public : 45 | int open(const char *ts_file_name, bool loop); 46 | int close(); 47 | int get(uint8_t *data, int size, int64_t &tm_ms, bool& jitter); 48 | 49 | int64_t generate_rts_file(const char *ts_file_name); 50 | 51 | private: 52 | char m_file_name[URL_MAX_LEN]; 53 | int m_rts_fd; 54 | int m_dts_pid; 55 | int64_t m_dts; 56 | int64_t m_pts; 57 | bool m_loop; 58 | CSLSArray m_array_data; 59 | int64_t m_udp_duration; 60 | int64_t m_readed_count; 61 | 62 | }; 63 | 64 | 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /slscore/common.hpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | #ifndef _COMMON_INCLUDE_ 26 | #define _COMMON_INCLUDE_ 27 | 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | using namespace std; 36 | 37 | /********************************************** 38 | * function return type 39 | */ 40 | /* error handling */ 41 | #if EDOM > 0 42 | #define SLSERROR(e) (-(e)) ///< Returns a negative error code from a POSIX error code, to return from library functions. 43 | #define SLSUNERROR(e) (-(e)) ///< Returns a POSIX error code from a library function error return value. 44 | #else 45 | /* Some platforms have E* and errno already negated. */ 46 | #define SLSERROR(e) (e) 47 | #define SLSUNERROR(e) (e) 48 | #endif 49 | 50 | #define MKTAG(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((unsigned)(d) << 24)) 51 | #define SLSERRTAG(a, b, c, d) (-(int)MKTAG(a, b, c, d)) 52 | 53 | #define SLS_OK SLSERRTAG(0x0,0x0,0x0,0x0 ) ///< OK 54 | #define SLS_ERROR SLSERRTAG(0x0,0x0,0x0,0x1 ) ///< 55 | #define SLSERROR_BSF_NOT_FOUND SLSERRTAG(0xF8,'B','S','F') ///< Bitstream filter not found 56 | #define SLSERROR_BUG SLSERRTAG( 'B','U','G','!') ///< Internal bug, also see SLSERROR_BUG2 57 | #define SLSERROR_BUFFER_TOO_SMALL SLSERRTAG( 'B','U','F','S') ///< Buffer too small 58 | #define SLSERROR_EOF SLSERRTAG( 'E','O','F',' ') ///< End of file 59 | #define SLSERROR_EXIT SLSERRTAG( 'E','X','I','T') ///< Immediate exit was requested; the called function should not be restarted 60 | #define SLSERROR_EXTERNAL SLSERRTAG( 'E','X','T',' ') ///< Generic error in an external library 61 | #define SLSERROR_INVALIDDATA SLSERRTAG( 'I','N','D','A') ///< Invalid data found when processing input 62 | #define SLSERROR_OPTION_NOT_FOUND SLSERRTAG(0xF8,'O','P','T') ///< Option not found 63 | #define SLSERROR_PROTOCOL_NOT_FOUND SLSERRTAG(0xF8,'P','R','O') ///< Protocol not found 64 | #define SLSERROR_STREAM_NOT_FOUND SLSERRTAG(0xF8,'S','T','R') ///< Stream of the StreamID not found 65 | #define SLSERROR_UNKNOWN SLSERRTAG( 'U','N','K','N') ///< Unknown error, typically from an external library 66 | 67 | 68 | #define SLSERROR_INVALID_SOCK SLSERRTAG( 'I','N','V','S') ///< Unknown error, typically from an external library 69 | /** 70 | * end 71 | **********************************************/ 72 | 73 | //#define SAFE_CREATE(p, class_name) { if (!p) new class_name(); } 74 | #define SAFE_DELETE(p) {if (p) { delete p; p = NULL; }} 75 | #define msleep(ms) usleep(ms*1000) 76 | 77 | #define TS_PACK_LEN 188 78 | #define TS_UDP_LEN 1316 //7*188 79 | #define SHORT_STR_MAX_LEN 256 80 | #define STR_MAX_LEN 1024 81 | #define URL_MAX_LEN STR_MAX_LEN 82 | #define STR_DATE_TIME_LEN 32 83 | #define INET_ADDRSTRLEN 16 84 | #define INET6_ADDRSTRLEN 46 85 | #define IP_MAX_LEN INET6_ADDRSTRLEN 86 | 87 | 88 | 89 | int64_t sls_gettime_ms(void);//rturn millisecond 90 | int64_t sls_gettime(void);//rturn microsecond 91 | void sls_gettime_fmt(char *dst, int64_t cur_time_sec, char *fmt); 92 | void sls_gettime_default_string(char *cur_time); 93 | char * sls_strupper(char * str); 94 | void sls_remove_marks(char *s); 95 | 96 | uint32_t sls_hash_key(const char *data, int len); 97 | int sls_gethostbyname(const char *hostname, char *ip); 98 | int sls_mkdir_p(const char *path); 99 | 100 | int sls_read_pid(); 101 | int sls_write_pid(int pid); 102 | int sls_remove_pid(); 103 | int sls_send_cmd(const char *cmd); 104 | 105 | void sls_split_string(std::string str, std::string separator, std::vector &result, int count=-1); 106 | std::string sls_find_string(std::vector &src, std::string &dst); 107 | 108 | 109 | /* 110 | * parse ts packet 111 | */ 112 | 113 | #define TS_SYNC_BYTE 0x47 114 | #define TS_PACK_LEN 188 115 | #define INVALID_PID -1 116 | #define PAT_PID 0 117 | #define INVALID_DTS_PTS -1 118 | #define MAX_PES_PAYLOAD 200 * 1024 119 | 120 | typedef struct ts_info { 121 | int es_pid; 122 | int64_t dts; 123 | int64_t pts; 124 | bool need_spspps; 125 | int sps_len; 126 | uint8_t sps[TS_PACK_LEN]; 127 | int pps_len; 128 | uint8_t pps[TS_PACK_LEN]; 129 | uint8_t ts_data[TS_UDP_LEN]; 130 | uint8_t pat[TS_PACK_LEN]; 131 | int pat_len; 132 | int pmt_pid; 133 | uint8_t pmt[TS_PACK_LEN]; 134 | int pmt_len; 135 | 136 | }; 137 | void sls_init_ts_info(ts_info *ti); 138 | int sls_parse_ts_info(const uint8_t *packet, ts_info *ti); 139 | 140 | 141 | #endif 142 | -------------------------------------------------------------------------------- /slscore/conf.hpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | 26 | #ifndef _CONF_INCLUDE_ 27 | #define _CONF_INCLUDE_ 28 | 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | using namespace std; 36 | 37 | /* 38 | * conf file structure 39 | * srt[root] 40 | * |_____ server[child] 41 | * | |_____ app[child] 42 | * | |__ app[sibling] 43 | * |_ server[sibling] 44 | * |_____ app[child] 45 | * |__ record[sibling] 46 | */ 47 | 48 | #define SLS_CONF_OK NULL 49 | #define SLS_CONF_ERROR (void *) -1 50 | #define SLS_CONF_OUT_RANGE "out of range" 51 | #define SLS_CONF_NAME_NOT_EXISTS "name not exist" 52 | #define SLS_CONF_WRONG_TYPE "wrong type" 53 | 54 | /* 55 | * conf cmd for set value by name dynamically 56 | */ 57 | struct sls_conf_cmd_t { 58 | const char *name; 59 | const char *mark; 60 | int offset; 61 | const char * (*set)(const char* v, sls_conf_cmd_t *cmd, void *conf); 62 | double min; ///< minimum valid value for the option 63 | double max; ///< maximum valid value for the option 64 | }; 65 | 66 | /* 67 | * set conf macro 68 | */ 69 | #define SLS_SET_CONF(conf, type, n, m, min, max)\ 70 | { #n,\ 71 | #m,\ 72 | offsetof(sls_conf_##conf##_t, n),\ 73 | sls_conf_set_##type,\ 74 | min,\ 75 | max,\ 76 | } 77 | 78 | const char * sls_conf_set_int (const char *v, sls_conf_cmd_t *cmd, void *conf); 79 | const char * sls_conf_set_string(const char *v, sls_conf_cmd_t *cmd, void *conf); 80 | const char * sls_conf_set_double(const char *v, sls_conf_cmd_t *cmd, void *conf); 81 | const char * sls_conf_set_bool (const char *v, sls_conf_cmd_t *cmd, void *conf); 82 | 83 | /** 84 | * runtime conf 85 | * all conf runtime classes are linked, such as frist->next->next->next. 86 | */ 87 | typedef struct sls_conf_base_t sls_conf_base_s; 88 | typedef sls_conf_base_t * (*create_conf_func)(); 89 | struct sls_runtime_conf_t { 90 | char * conf_name; 91 | // char * higher_conf_names;//if allow existing in one than one higher conf , split with '|' 92 | create_conf_func create_fn; 93 | sls_conf_cmd_t * conf_cmd; 94 | int conf_cmd_size; 95 | 96 | sls_runtime_conf_t * next; 97 | static sls_runtime_conf_t * first; 98 | sls_runtime_conf_t(char * c, create_conf_func f, sls_conf_cmd_t * cmd, int len); 99 | }; 100 | 101 | /* 102 | * conf base, each actual conf must inherit from it, 103 | * decare a new conf please use macro SLS_CONF_DYNAMIC_DECLARE_BEGIN 104 | */ 105 | struct sls_conf_base_t { 106 | char * name; 107 | sls_conf_base_t * sibling; 108 | sls_conf_base_t * child; 109 | }; 110 | 111 | /** 112 | * conf dynamic macro 113 | */ 114 | #define SLS_CONF_DYNAMIC_DECLARE_BEGIN(c_n)\ 115 | struct sls_conf_##c_n##_t : public sls_conf_base_t {\ 116 | static sls_runtime_conf_t runtime_conf;\ 117 | static sls_conf_base_t * create_conf(); 118 | 119 | #define SLS_CONF_DYNAMIC_DECLARE_END \ 120 | }; 121 | 122 | #define SLS_CONF_DYNAMIC_IMPLEMENT(c_n)\ 123 | sls_conf_base_t * sls_conf_##c_n##_t::create_conf()\ 124 | {\ 125 | sls_conf_base_t * p = new sls_conf_##c_n##_t ;\ 126 | memset(p, 0, sizeof(sls_conf_##c_n##_t));\ 127 | p->child = NULL;\ 128 | p->sibling = NULL;\ 129 | p->name = sls_conf_##c_n##_t::runtime_conf.conf_name;\ 130 | return p;\ 131 | }\ 132 | sls_runtime_conf_t sls_conf_##c_n##_t::runtime_conf(\ 133 | #c_n,\ 134 | sls_conf_##c_n##_t::create_conf,\ 135 | conf_cmd_##c_n,\ 136 | sizeof(conf_cmd_##c_n)/sizeof(sls_conf_cmd_t)\ 137 | ); 138 | 139 | /* 140 | * conf cmd dynamic macro 141 | */ 142 | #define SLS_CONF_CMD_DYNAMIC_DECLARE_BEGIN(c_n)\ 143 | static sls_conf_cmd_t conf_cmd_##c_n[] = { 144 | 145 | #define SLS_CONF_CMD_DYNAMIC_DECLARE_END \ 146 | }; 147 | 148 | #define SLS_CONF_GET_CONF_INFO(c_name)\ 149 | (sls_conf_##c_name *)sls_conf_##c_name::runtime_conf_##c_name.conf_name; 150 | 151 | /* 152 | * conf api functions 153 | */ 154 | int sls_conf_get_conf_count(sls_conf_base_t *c); 155 | int sls_conf_open (const char * conf_file); 156 | void sls_conf_close(); 157 | 158 | /** 159 | * parse the argv 160 | */ 161 | #define SLS_SET_OPT(type, c, n, m, min, max)\ 162 | { #c,\ 163 | #m,\ 164 | offsetof(sls_opt_t, n),\ 165 | sls_conf_set_##type,\ 166 | min,\ 167 | max,\ 168 | } 169 | //1: add new parameter here 170 | struct sls_opt_t { 171 | char conf_file_name[1024];//-c 172 | char c_cmd[256]; //-r 173 | char log_level[256]; //-l log level 174 | // int xxx; //-x example 175 | }; 176 | 177 | int sls_parse_argv(int argc, char * argv[], sls_opt_t * sls_opt, sls_conf_cmd_t *conf_cmd_opt, int cmd_size); 178 | 179 | 180 | sls_conf_cmd_t * sls_conf_find(const char *n, sls_conf_cmd_t *cmd, int size); 181 | sls_conf_base_t * sls_conf_get_root_conf(); 182 | vector sls_conf_string_split(const string& str, const string& delim); 183 | 184 | 185 | 186 | #endif 187 | -------------------------------------------------------------------------------- /srt-live-client.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2019-2020 Edward.Wu 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | using namespace std; 31 | 32 | #include "SLSLog.hpp" 33 | #include "SLSClient.hpp" 34 | 35 | /* 36 | * ctrl + c controller 37 | */ 38 | static bool b_exit = 0; 39 | static void ctrl_c_handler(int s){ 40 | printf("\ncaught signal %d, exit.\n",s); 41 | b_exit = true; 42 | } 43 | 44 | 45 | /** 46 | * usage information 47 | */ 48 | #define SLS_MAJOR_VERSION "1" 49 | #define SLS_MIN_VERSION "1" 50 | #define SLS_TEST_VERSION "x" 51 | static void usage() 52 | { 53 | printf("-------------------------------------------------\n"); 54 | printf(" srt-live-client \n"); 55 | printf(" v%s.%s.%s \n", SLS_MAJOR_VERSION, SLS_MIN_VERSION, SLS_TEST_VERSION); 56 | printf("-------------------------------------------------\n"); 57 | printf(" -r srt_url [-o out_file_name] [-c worker_count] \n"); 58 | printf(" -r srt_url -i ts_file_name \n"); 59 | printf(" \n"); 60 | } 61 | 62 | struct sls_opt_client_t { 63 | char input_ts_file[1024]; 64 | char srt_url[1024]; 65 | char out_file_name[1024]; 66 | char ts_file_name[1024]; 67 | int worker_count; 68 | bool loop; 69 | // int xxx; //-x example 70 | }; 71 | 72 | 73 | int main(int argc, char* argv[]) 74 | { 75 | struct sigaction sigIntHandler; 76 | sls_opt_client_t sls_opt; 77 | 78 | int ret = SLS_OK; 79 | usage(); 80 | 81 | //parse cmd line 82 | if (argc < 3) { 83 | sls_log(SLS_LOG_INFO, "srt live client, no enough parameters, EXIT!"); 84 | return SLS_OK; 85 | } 86 | 87 | //parset argv 88 | memset(&sls_opt, 0, sizeof(sls_opt)); 89 | int i = 1; 90 | while (i < argc) { 91 | sls_remove_marks(argv[i]); 92 | if (strcmp("-r", argv[i]) == 0) { 93 | i ++; 94 | sls_remove_marks(argv[i]); 95 | strcpy(sls_opt.srt_url, argv[i++]); 96 | } else if (strcmp("-i", argv[i]) == 0) { 97 | i ++; 98 | sls_remove_marks(argv[i]); 99 | strcpy(sls_opt.ts_file_name, argv[i++]); 100 | } else if (strcmp("-o", argv[i]) == 0) { 101 | i ++; 102 | sls_remove_marks(argv[i]); 103 | strcpy(sls_opt.out_file_name, argv[i++]); 104 | } else if (strcmp("-c", argv[i]) == 0) { 105 | i ++; 106 | sls_remove_marks(argv[i]); 107 | sls_opt.worker_count = atoi(argv[i++]); 108 | } else if (strcmp("-l", argv[i]) == 0) { 109 | i ++; 110 | sls_remove_marks(argv[i]); 111 | sls_opt.loop = atoi(argv[i++]); 112 | } else { 113 | sls_log(SLS_LOG_INFO, "srt live client, wrong parameter '%s', EXIT!", argv[i]); 114 | return SLS_OK; 115 | } 116 | } 117 | CSLSClient sls_client; 118 | if (strlen(sls_opt.ts_file_name) > 0) { 119 | if (SLS_OK != sls_client.push(sls_opt.srt_url, sls_opt.ts_file_name, sls_opt.loop)) { 120 | sls_log(SLS_LOG_INFO, "sls_client.push failed, EXIT!"); 121 | return SLS_ERROR; 122 | } 123 | } else { 124 | if (SLS_OK != sls_client.play(sls_opt.srt_url, sls_opt.out_file_name)) { 125 | sls_log(SLS_LOG_INFO, "sls_client.play failed, EXIT!"); 126 | return SLS_ERROR; 127 | } 128 | for(i = 1; i < sls_opt.worker_count; i++) { 129 | pid_t fpid; //fpid表示fork函数返回的值 130 | fpid=fork(); 131 | if (fpid < 0){ 132 | printf("srt live client, error in fork!"); 133 | }else if (fpid == 0) { 134 | printf("srt live client, i am the child process, my process id is %d/n",getpid()); 135 | break; 136 | }else { 137 | printf("srt live client, i am the parent process, my process id is %d/n",getpid()); 138 | } 139 | } 140 | } 141 | 142 | 143 | //ctrl + c to exit 144 | sigIntHandler.sa_handler = ctrl_c_handler; 145 | sigemptyset(&sigIntHandler.sa_mask); 146 | sigIntHandler.sa_flags = 0; 147 | sigaction(SIGINT, &sigIntHandler, 0); 148 | 149 | sls_log(SLS_LOG_INFO, "\nsrt live client is running..."); 150 | while(!b_exit) 151 | { 152 | //printf log info 153 | int64_t kb = sls_client.get_bitrate() ; 154 | printf("\rsrt live client, cur bitrate=%lld(kb)", kb); 155 | 156 | int ret = sls_client.handler(); 157 | if ( ret > 0) { 158 | continue; 159 | } else if (0 == ret) { 160 | msleep(1); 161 | } else { 162 | break; 163 | } 164 | } 165 | 166 | sls_log(SLS_LOG_INFO, "exit, stop srt live client..."); 167 | sls_client.close(); 168 | sls_log(SLS_LOG_INFO, "exit, bye bye!"); 169 | 170 | return 0; 171 | } 172 | -------------------------------------------------------------------------------- /start_srt.bat: -------------------------------------------------------------------------------- 1 | docker start sls -------------------------------------------------------------------------------- /stop_srt.bat: -------------------------------------------------------------------------------- 1 | docker stop sls --------------------------------------------------------------------------------