mirror of
				https://github.com/ossrs/srs.git
				synced 2025-03-09 15:49:59 +00:00 
			
		
		
		
	Support MIPS 64bits for loongson 3A4000/3B3000. v5.0.34
This commit is contained in:
		
							parent
							
								
									aba6667357
								
							
						
					
					
						commit
						1589858cb0
					
				
					 16 changed files with 543 additions and 185 deletions
				
			
		
							
								
								
									
										3
									
								
								trunk/3rdparty/st-srs/README.md
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								trunk/3rdparty/st-srs/README.md
									
										
									
									
										vendored
									
									
								
							|  | @ -35,6 +35,8 @@ For Linux aarch64, which fail with `Unknown CPU architecture`: | |||
| make linux-debug EXTRA_CFLAGS="-D__aarch64__" | ||||
| ``` | ||||
| 
 | ||||
| > Note: For more CPU architectures, please see [#22](https://github.com/ossrs/state-threads/issues/22) | ||||
| 
 | ||||
| Linux with valgrind: | ||||
| 
 | ||||
| ```bash | ||||
|  | @ -110,6 +112,7 @@ The branch [srs](https://github.com/ossrs/state-threads/tree/srs) will be patche | |||
| - [x] LOONGARCH: Support loongarch for loongson CPU, [#24](https://github.com/ossrs/state-threads/issues/24).  | ||||
| - [x] System: Support Multiple Threads for Linux and Darwin. [#19](https://github.com/ossrs/state-threads/issues/19), [srs#2188](https://github.com/ossrs/srs/issues/2188). | ||||
| - [x] RISCV: Support RISCV for RISCV CPU, [#24](https://github.com/ossrs/state-threads/pull/28). | ||||
| - [x] MIPS: Support Linux/MIPS64 for loongson 3A4000/3B3000, [#21](https://github.com/ossrs/state-threads/pull/21). | ||||
| - [ ] IDE: Support CLion for debugging and learning. | ||||
| - [ ] System: Support sendmmsg for UDP, [#12](https://github.com/ossrs/state-threads/issues/12). | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										64
									
								
								trunk/3rdparty/st-srs/auto/codecov.sh
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										64
									
								
								trunk/3rdparty/st-srs/auto/codecov.sh
									
										
									
									
										vendored
									
									
								
							|  | @ -1,52 +1,38 @@ | |||
| #!/bin/bash | ||||
| 
 | ||||
| # In .circleci/config.yml, generate *.gcno with | ||||
| #       ./configure --gcov --without-research --without-librtmp && make | ||||
| # and generate *.gcda by | ||||
| #       ./objs/srs_utest | ||||
| 
 | ||||
| # Workdir is objs/cover. | ||||
| workdir=`pwd`/codecov && rm -rf $workdir | ||||
| 
 | ||||
| # Tool git is required to map the right path. | ||||
| git --version >/dev/null 2>&1 | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then echo "Tool git is required, ret=$ret"; exit $ret; fi | ||||
| # Workdir is obj/coverage. | ||||
| workdir=`pwd`/coverage | ||||
| 
 | ||||
| # Create trunk under workdir. | ||||
| mkdir -p $workdir && cd $workdir | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then echo "Enter workdir failed, ret=$ret"; exit $ret; fi | ||||
| 
 | ||||
| # Collect all *.gcno and *.gcda to objs/cover. | ||||
| cd $workdir && for file in $(cd .. && ls *.c); do | ||||
|   cp ../$file $file && echo "Copy $file" && | ||||
|   if [[ -f ../obj/${file%.*}.gcno ]]; then | ||||
|     cp ../obj/${file%.*}.* . | ||||
|   fi | ||||
| done | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then echo "Collect *.gcno and *.gcda failed, ret=$ret"; exit $ret; fi | ||||
| 
 | ||||
| # Generate *.gcov for coverage. | ||||
| cd $workdir && | ||||
| for file in $(ls *.c); do | ||||
|     gcov $file -o `dirname $file` | ||||
|     ret=$?; if [[ $ret -ne 0 ]]; then echo "Collect $file failed, ret=$ret"; exit $ret; fi | ||||
| done | ||||
| 
 | ||||
| # Filter the gcov files, remove utest or gtest. | ||||
| cd $workdir && | ||||
| rm -f *gtest*.gcov *utest*.gcov | ||||
| ret=$?; if [[ $ret -ne 0 ]]; then echo "Cook gcov files failed, ret=$ret"; exit $ret; fi | ||||
| CODECOV_ARGS="" | ||||
| if [[ $ST_PROJECT != '' ]]; then | ||||
|   # -R root dir  Used when not in git/hg project to identify project root directory | ||||
|   # -p dir       Project root directory. Also used when preparing gcov | ||||
|   CODECOV_ARGS="$CODECOV_ARGS -R $ST_PROJECT -p $ST_PROJECT" | ||||
| fi | ||||
| if [[ $ST_BRANCH != '' ]]; then | ||||
|   # -B branch    Specify the branch name | ||||
|   CODECOV_ARGS="$CODECOV_ARGS -B $ST_BRANCH" | ||||
| fi | ||||
| if [[ $ST_SHA != '' ]]; then | ||||
|   # -C sha       Specify the commit sha | ||||
|   CODECOV_ARGS="$CODECOV_ARGS -C $ST_SHA" | ||||
| fi | ||||
| if [[ $ST_PR != '' ]]; then | ||||
|   # -P pr        Specify the pull request number | ||||
|   CODECOV_ARGS="$CODECOV_ARGS -P $ST_PR" | ||||
| fi | ||||
| 
 | ||||
| # Upload report with *.gcov | ||||
| # Remark: The file codecov.yml is not neccessary. It literally depends on git. | ||||
| # Note: The right path is like: | ||||
| #       https://codecov.io/gh/ossrs/srs/src/3.0release/trunk/src/protocol/srs_rtmp_stack.cpp | ||||
| #       https://codecov.io/gh/ossrs/srs/src/20fbb4466fdc8ba5d810b8570df6004063212838/trunk/src/protocol/srs_rtmp_stack.cpp | ||||
| # Remark: It takes a few minutes to sync with github, so it might not available when CircleCI is done. | ||||
| #       https://circleci.com/gh/ossrs/srs/tree/3.0release | ||||
| # | ||||
| # Note: Use '-X gcov' to avoid generate the gcov files again. | ||||
| #       https://app.codecov.io/gh/ossrs/state-threads/blob/srs/sched.c | ||||
| #       https://app.codecov.io/gh/ossrs/state-threads/blob/593cf748f055ca383867003e409a423efd8f8f86/sched.c | ||||
| cd $workdir && | ||||
| export CODECOV_TOKEN="0d616496-f781-4e7c-b285-d1f70a1cdf24" && | ||||
| bash <(curl -s https://codecov.io/bash) -X gcov && | ||||
| export CODECOV_TOKEN="$CODECOV_TOKEN" && | ||||
| bash <(curl -s https://codecov.io/bash) $CODECOV_ARGS -f '!*gtest*' -f '!*c++*' && | ||||
| echo "Done" && exit 0 | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										20
									
								
								trunk/3rdparty/st-srs/auto/coverage.sh
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										20
									
								
								trunk/3rdparty/st-srs/auto/coverage.sh
									
										
									
									
										vendored
									
									
								
							|  | @ -1,23 +1,14 @@ | |||
| #!/bin/bash | ||||
| 
 | ||||
| if [[ ! -f utest/gtest/include/gtest/gtest.h ]]; then | ||||
|   ( | ||||
|     cd utest && rm -rf gtest && | ||||
|     curl https://github.com/google/googletest/archive/release-1.6.0.tar.gz -L -o googletest-release-1.6.0.tar.gz && | ||||
|     tar xf googletest-release-1.6.0.tar.gz && | ||||
|     ln -sf googletest-release-1.6.0 gtest && | ||||
|     echo "Setup gtest ok" | ||||
|   ) | ||||
| fi | ||||
| if [[ ! -f utest/gtest/include/gtest/gtest.h ]]; then | ||||
|   echo "No utest/gtest, please download from https://github.com/google/googletest/releases/tag/release-1.6.0" | ||||
| if [[ ! -f utest/gtest-fit/googletest/include/gtest/gtest.h ]]; then | ||||
|   echo "No utest/gtest, please download from https://github.com/google/googletest/releases/tag/release-1.11.0" | ||||
|   exit -1 | ||||
| else | ||||
|   echo "Check utest/gtest ok" | ||||
| fi | ||||
| 
 | ||||
| if [[ $(gcovr --version >/dev/null && echo yes) != yes ]]; then | ||||
|   echo "Please install gcovr: https://github.com/ossrs/state-threads/tree/srs#utest-and-coverage" | ||||
|   echo "Please install gcovr" | ||||
|   exit -1 | ||||
| fi | ||||
| 
 | ||||
|  | @ -34,6 +25,9 @@ fi | |||
| 
 | ||||
| echo "Generating coverage" | ||||
| mkdir -p coverage && | ||||
| gcovr -r . -e LINUX -e DARWIN -e examples --html --html-details -o coverage/st.html && | ||||
| (cd obj && rm -f gtest-all.gcda gtest-all.gcno) && | ||||
| (cd obj && rm -f *.c *.cpp gtest-fit && ln -sf ../*.c . && ln -sf ../utest/*.cpp && ln -sf ../utest/gtest-fit .) && | ||||
| (cd obj && gcovr --gcov-exclude gtest --html --html-details -o ../coverage/st.html) && | ||||
| (cd obj && rm -f *.c *.cpp gtest-fit) && | ||||
| echo "Coverage report at coverage/st.html" && | ||||
| open coverage/st.html | ||||
|  |  | |||
							
								
								
									
										15
									
								
								trunk/3rdparty/st-srs/auto/fast.sh
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								trunk/3rdparty/st-srs/auto/fast.sh
									
										
									
									
										vendored
									
									
								
							|  | @ -22,19 +22,12 @@ ret=$?; if [[ 0 -ne $ret ]]; then echo "Make ST utest fail, ret=$ret"; exit $ret | |||
| 
 | ||||
| echo "Generating coverage" | ||||
| mkdir -p coverage && | ||||
| gcovr -r . -e LINUX -e DARWIN -e examples --html --html-details -o coverage/st.html && | ||||
| (cd obj && rm -f gtest-all.gcda gtest-all.gcno) && | ||||
| (cd obj && rm -f *.c *.cpp gtest-fit && ln -sf ../*.c . && ln -sf ../utest/*.cpp && ln -sf ../utest/gtest-fit .) && | ||||
| (cd obj && gcovr --gcov-exclude gtest --html --html-details -o ../coverage/st.html) && | ||||
| (cd obj && rm -f *.c *.cpp gtest-fit) && | ||||
| echo "Coverage report at coverage/st.html" && | ||||
| open coverage/st.html | ||||
| 
 | ||||
| popd | ||||
| echo "UTest done, restore $(pwd)" | ||||
| 
 | ||||
| cat << END > /dev/stdout | ||||
| 
 | ||||
|   # CLI For DARWIN | ||||
|   cd $PWD && rm -f ./obj/*.gcda && | ||||
|   make darwin-debug-gcov && ./obj/st_utest && | ||||
|   mkdir -p coverage && gcovr -r . -e LINUX -e DARWIN -e examples --html --html-details -o coverage/st.html && | ||||
|   open coverage/st.html | ||||
| 
 | ||||
| END | ||||
							
								
								
									
										6
									
								
								trunk/3rdparty/st-srs/md.h
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								trunk/3rdparty/st-srs/md.h
									
										
									
									
										vendored
									
									
								
							|  | @ -182,6 +182,10 @@ | |||
|                 #error "ARM/Linux pre-glibc2 not supported yet" | ||||
|             #endif /* defined(__GLIBC__) && __GLIBC__ >= 2 */ | ||||
| 
 | ||||
|         #elif defined(__mips64) | ||||
|             /* https://github.com/ossrs/state-threads/issues/21 */ | ||||
|             #define MD_USE_BUILTIN_SETJMP | ||||
|             #define MD_GET_SP(_t) *((long *)&((_t)->context[0].__jmpbuf[0])) | ||||
|         #elif defined(__mips__) | ||||
|             /* https://github.com/ossrs/state-threads/issues/21 */ | ||||
|             #define MD_USE_BUILTIN_SETJMP | ||||
|  | @ -191,7 +195,7 @@ | |||
|             #define MD_USE_BUILTIN_SETJMP | ||||
|             #define MD_GET_SP(_t) *((long *)&((_t)->context[0].__jmpbuf[0])) | ||||
| 
 | ||||
|         #elif defined(__loongarch__) | ||||
|         #elif defined(__loongarch64) | ||||
|             /* https://github.com/ossrs/state-threads/issues/24 */ | ||||
|             #define MD_USE_BUILTIN_SETJMP | ||||
|             #define MD_GET_SP(_t) *((long *)&((_t)->context[0].__jmpbuf[0])) | ||||
|  |  | |||
							
								
								
									
										80
									
								
								trunk/3rdparty/st-srs/md_linux.S
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										80
									
								
								trunk/3rdparty/st-srs/md_linux.S
									
										
									
									
										vendored
									
									
								
							|  | @ -433,9 +433,87 @@ | |||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #elif defined(__mips64) | ||||
| 
 | ||||
|     /****************************************************************/ | ||||
|     /* For MIPS64, see https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MIPS_Architecture_MIPS64_InstructionSet_%20AFP_P_MD00087_06.05.pdf */ | ||||
| 
 | ||||
|     /* | ||||
|      * Internal __jmp_buf layout | ||||
|      */ | ||||
|     #define JB_SP  0    /* Stack pointer */ | ||||
|     #define JB_RA  11   /* Return address */ | ||||
|     #define JB_GP  1    /* Global pointer */ | ||||
|     #define JB_S0  3    /* S0-S7, Saved temporaries */ | ||||
|     #define JB_S1  4    /* S0-S7, Saved temporaries */ | ||||
|     #define JB_S2  5    /* S0-S7, Saved temporaries */ | ||||
|     #define JB_S3  6    /* S0-S7, Saved temporaries */ | ||||
|     #define JB_S4  7    /* S0-S7, Saved temporaries */ | ||||
|     #define JB_S5  8    /* S0-S7, Saved temporaries */ | ||||
|     #define JB_S6  9    /* S0-S7, Saved temporaries */ | ||||
|     #define JB_S7  10   /* S0-S7, Saved temporaries */ | ||||
|     #define JB_FP  2    /* FP/S8 Frame pointer */ | ||||
| 
 | ||||
|     	.file "md_linux.S" | ||||
|     	.text | ||||
| 
 | ||||
|     	/* _st_md_cxt_save(__jmp_buf env) */ /* The env is $a0, https://en.wikipedia.org/wiki/MIPS_architecture#Calling_conventions */ | ||||
|     	.globl _st_md_cxt_save
 | ||||
|     	.type _st_md_cxt_save, %function | ||||
|     	.align 2
 | ||||
|     _st_md_cxt_save: | ||||
|         sd $sp,  0($a0) /* Save sp to env[0],  *(long*)($a0+ 0) =sp */ | ||||
|         sd $ra,  8($a0) /* Save ra to env[1],  *(long*)($a0+ 8)=ra, the return address, https://chortle.ccsu.edu/AssemblyTutorial/Chapter-26/ass26_4.html */ | ||||
|         sd $gp, 16($a0) /* Save gp to env[2],  *(long*)($a0+16) =gp */ | ||||
|         sd $s0, 24($a0) /* Save s0 to env[3],  *(long*)($a0+24)=s0 */ | ||||
|         sd $s1, 32($a0) /* Save s1 to env[4],  *(long*)($a0+32)=s1 */ | ||||
|         sd $s2, 40($a0) /* Save s2 to env[5],  *(long*)($a0+40)=s2 */ | ||||
|         sd $s3, 48($a0) /* Save s3 to env[6],  *(long*)($a0+48)=s3 */ | ||||
|         sd $s4, 56($a0) /* Save s4 to env[7],  *(long*)($a0+56)=s4 */ | ||||
|         sd $s5, 64($a0) /* Save s5 to env[8],  *(long*)($a0+64)=s5 */ | ||||
|         sd $s6, 72($a0) /* Save s6 to env[9],  *(long*)($a0+72)=s6 */ | ||||
|         sd $s7, 80($a0) /* Save s7 to env[10], *(long*)($a0+80)=s7 */ | ||||
|         sd $fp, 88($a0) /* Save fp to env[11], *(long*)($a0+88) =fp */ | ||||
|         li $v0, 0       /* Set return value to 0 */ | ||||
|         jr $ra          /* Return */ | ||||
| 
 | ||||
|     	.size _st_md_cxt_save, .-_st_md_cxt_save | ||||
| 
 | ||||
|     /****************************************************************/ | ||||
| 
 | ||||
|     	/* _st_md_cxt_restore(__jmp_buf env, int val) */ | ||||
|     	.globl _st_md_cxt_restore
 | ||||
|     	.type _st_md_cxt_restore, %function | ||||
|     	.align 2
 | ||||
|     _st_md_cxt_restore: | ||||
|         ld $sp,  0($a0) /* Load sp from env[0],  sp=*(long*)($a0+ 0)  */ | ||||
|         ld $ra,  8($a0) /* Load sp from env[1],  ra=*(long*)($a0+ 8), the saved return address */ | ||||
|         ld $gp, 16($a0) /* Load sp from env[2],  gp=*(long*)($a0+16)  */ | ||||
|         ld $s0, 24($a0) /* Load sp from env[3],  s0=*(long*)($a0+24) */ | ||||
|         ld $s1, 32($a0) /* Load sp from env[4],  s1=*(long*)($a0+32) */ | ||||
|         ld $s2, 40($a0) /* Load sp from env[5],  s2=*(long*)($a0+40) */ | ||||
|         ld $s3, 48($a0) /* Load sp from env[6],  s3=*(long*)($a0+48) */ | ||||
|         ld $s4, 56($a0) /* Load sp from env[7],  s4=*(long*)($a0+56) */ | ||||
|         ld $s5, 64($a0) /* Load sp from env[8],  s5=*(long*)($a0+64) */ | ||||
|         ld $s6, 72($a0) /* Load sp from env[9],  s6=*(long*)($a0+72) */ | ||||
|         ld $s7, 80($a0) /* Load sp from env[10], s7=*(long*)($a0+80) */ | ||||
|         ld $fp, 88($a0) /* Load sp from env[2],  fp=*(long*)($a0+88)  */ | ||||
|         li $v0, 1       /* Set return value to 1 */ | ||||
|         jr $ra          /* Return to the saved return address */ | ||||
| 
 | ||||
|     	.size _st_md_cxt_restore, .-_st_md_cxt_restore | ||||
| 
 | ||||
|     /****************************************************************/ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #elif defined(__mips__) | ||||
| 
 | ||||
|     /****************************************************************/ | ||||
|     /* For MIPS32, see https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00565-2B-MIPS32-QRC-01.01.pdf */ | ||||
| 
 | ||||
|     /* | ||||
|      * Internal __jmp_buf layout | ||||
|  | @ -513,7 +591,7 @@ | |||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #elif defined(__loongarch__) | ||||
| #elif defined(__loongarch64) | ||||
| 
 | ||||
|     /****************************************************************/ | ||||
| 
 | ||||
|  |  | |||
|  | @ -9,7 +9,8 @@ int main(int argc, char** argv) | |||
| { | ||||
|     st_init(); | ||||
| 
 | ||||
|     for (int i = 0; i < 10000; i++) { | ||||
|     int i; | ||||
|     for (i = 0; i < 10000; i++) { | ||||
|         printf("#%03d, Hello, state-threads world!\n", i); | ||||
|         st_sleep(1); | ||||
|     } | ||||
|  |  | |||
							
								
								
									
										68
									
								
								trunk/3rdparty/st-srs/tools/porting/porting.c
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										68
									
								
								trunk/3rdparty/st-srs/tools/porting/porting.c
									
										
									
									
										vendored
									
									
								
							|  | @ -25,11 +25,23 @@ int main(int argc, char** argv) | |||
|     // https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00565-2B-MIPS32-QRC-01.01.pdf
 | ||||
|     printf("__mips__: %d, __mips: %d, _MIPSEL: %d\n", __mips__, __mips, _MIPSEL); | ||||
| #endif | ||||
| #ifdef __mips64 | ||||
|     printf("__mips64: %d\n", __mips64); | ||||
| #endif | ||||
| #ifdef __x86_64__ | ||||
|     printf("__x86_64__: %d\n", __x86_64__); | ||||
| #endif | ||||
| #ifdef __loongarch__ | ||||
|     printf("__loongarch__: %d, __loongarch64 :%d\n", __loongarch__, __loongarch64); | ||||
| #ifdef __loongarch64 | ||||
|     printf("__loongarch__: %d __loongarch64: %d\n", __loongarch__, __loongarch64); | ||||
| #endif | ||||
| #ifdef __riscv | ||||
|     printf("__riscv: %d\n", __riscv); | ||||
| #endif | ||||
| #ifdef __arm__ | ||||
|     printf("__arm__: %d\n", __arm__); | ||||
| #endif | ||||
| #ifdef __aarch64__ | ||||
|     printf("__aarch64__: %d\n", __aarch64__); | ||||
| #endif | ||||
| 
 | ||||
|     printf("\nCompiler specs:\n"); | ||||
|  | @ -71,7 +83,52 @@ int foo_return_one_arg1(int r0) | |||
| } | ||||
| 
 | ||||
| #ifdef __linux__ | ||||
| #ifdef __mips__ | ||||
| 
 | ||||
| #if defined(__riscv) || defined(__arm__) || defined(__aarch64__) | ||||
| void print_jmpbuf() { | ||||
| } | ||||
| #elif __mips64 | ||||
| void print_jmpbuf() | ||||
| { | ||||
|     // https://en.wikipedia.org/wiki/MIPS_architecture#Calling_conventions
 | ||||
|     register void* ra asm("ra"); | ||||
|     register void* gp asm("gp"); | ||||
|     register void* sp asm("sp"); | ||||
|     register void* fp asm("fp"); | ||||
|     // $s0–$s7	$16–$23	saved temporaries
 | ||||
|     register void* s0 asm("s0"); | ||||
|     register void* s1 asm("s1"); | ||||
|     register void* s2 asm("s2"); | ||||
|     register void* s3 asm("s3"); | ||||
|     register void* s4 asm("s4"); | ||||
|     register void* s5 asm("s5"); | ||||
|     register void* s6 asm("s6"); | ||||
|     register void* s7 asm("s7"); | ||||
| 
 | ||||
|     /*
 | ||||
|     typedef unsigned long long __jmp_buf[13]; | ||||
|     typedef struct __jmp_buf_tag { | ||||
|          __jmp_buf __jmpbuf; | ||||
|         int __mask_was_saved; | ||||
|         __sigset_t __saved_mask; | ||||
|     } jmp_buf[1]; | ||||
|     */ | ||||
|     jmp_buf ctx = {0}; | ||||
|     int r0 = setjmp(ctx); | ||||
|     if (!r0) { | ||||
|         longjmp(ctx, 1); | ||||
|     } | ||||
| 
 | ||||
|     printf("ra=%p, sp=%p, s0=%p, s1=%p, s2=%p, s3=%p, s4=%p, s5=%p, s6=%p, s7=%p, fp=%p, gp=%p\n", | ||||
|         ra, sp, s0, s1, s2, s3, s4, s5, s6, s7, fp, gp); | ||||
| 
 | ||||
|     int nn_jb = sizeof(ctx[0].__jmpbuf); | ||||
|     printf("sizeof(jmp_buf)=%d (unsigned long long [%d])\n", nn_jb, nn_jb/8); | ||||
| 
 | ||||
|     unsigned char* p = (unsigned char*)ctx[0].__jmpbuf; | ||||
|     print_buf(p, nn_jb); | ||||
| } | ||||
| #elif __mips__ | ||||
| void print_jmpbuf() | ||||
| { | ||||
|     // https://en.wikipedia.org/wiki/MIPS_architecture#Calling_conventions
 | ||||
|  | @ -112,7 +169,7 @@ void print_jmpbuf() | |||
|     unsigned char* p = (unsigned char*)ctx[0].__jb; | ||||
|     print_buf(p, nn_jb); | ||||
| } | ||||
| #elif __loongarch__ | ||||
| #elif __loongarch64 | ||||
| void print_jmpbuf() | ||||
| { | ||||
|     // https://github.com/ossrs/state-threads/issues/24#porting
 | ||||
|  | @ -192,7 +249,8 @@ void print_buf(unsigned char* p, int nn_jb) | |||
| { | ||||
|     printf("    "); | ||||
| 
 | ||||
|     for (int i = 0; i < nn_jb; i++) { | ||||
|     int i; | ||||
|     for (i = 0; i < nn_jb; i++) { | ||||
|         printf("0x%02x ", (unsigned char)p[i]); | ||||
| 
 | ||||
|         int newline = ((i + 1) % sizeof(void*)); | ||||
|  |  | |||
							
								
								
									
										2
									
								
								trunk/3rdparty/st-srs/tools/verify/verify.c
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								trunk/3rdparty/st-srs/tools/verify/verify.c
									
										
									
									
										vendored
									
									
								
							|  | @ -48,7 +48,7 @@ void verify_jmpbuf() | |||
|     unsigned char* p = (unsigned char*)ctx[0].__jb; | ||||
|     print_buf(p, nn_jb); | ||||
| } | ||||
| #elif __loongarch__ | ||||
| #elif __loongarch64 | ||||
| void verify_jmpbuf() | ||||
| { | ||||
|     // https://github.com/ossrs/state-threads/issues/24#porting
 | ||||
|  |  | |||
							
								
								
									
										25
									
								
								trunk/3rdparty/st-srs/utest/Makefile
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										25
									
								
								trunk/3rdparty/st-srs/utest/Makefile
									
										
									
									
										vendored
									
									
								
							|  | @ -4,7 +4,7 @@ ST_DIR = .. | |||
| # The main dir of st utest.
 | ||||
| ST_UTEST = . | ||||
| # The main dir of gtest.
 | ||||
| GTEST_DIR = $(ST_UTEST)/gtest | ||||
| GTEST_DIR = $(ST_UTEST)/gtest-fit/googletest | ||||
| 
 | ||||
| # Flags passed to the C++ compiler.
 | ||||
| CXXFLAGS +=  -g -O0 -std=c++11 | ||||
|  | @ -45,16 +45,29 @@ $(ST_DIR)/obj/gtest.a : $(ST_DIR)/obj/gtest-all.o | |||
| ST_UTEST_DEPS = $(ST_DIR)/obj/libst.a | ||||
| 
 | ||||
| # Depends, utest header files
 | ||||
| UTEST_DEPS = $(ST_UTEST)/st_utest.hpp | ||||
| UTEST_DEPS = $(ST_UTEST)/st_utest.hpp Makefile | ||||
| 
 | ||||
| # Compile all sources files at current directory. For example:
 | ||||
| # 		(st_utest.cpp st_utest_coroutines.cpp st_utest_tcp.cpp)
 | ||||
| SOURCE_FILES = $(shell ls *.cpp) | ||||
| #
 | ||||
| # Convert all source files to object files. For example:
 | ||||
| # 		(st_utest.o st_utest_coroutines.o st_utest_tcp.o)
 | ||||
| # https://ftp.gnu.org/old-gnu/Manuals/make-3.79.1/html_chapter/make_8.html
 | ||||
| OBJECTS_FILES = $(patsubst %.cpp,%.o,$(SOURCE_FILES)) | ||||
| #
 | ||||
| # Prefix object files to objects. For example:
 | ||||
| # 		($(ST_DIR)/obj/st_utest.o $(ST_DIR)/obj/st_utest_coroutines.o $(ST_DIR)/obj/st_utest_tcp.o)
 | ||||
| OBJECTS = $(addprefix $(ST_DIR)/obj/,$(OBJECTS_FILES)) | ||||
| 
 | ||||
| # Objects, build each object of utest
 | ||||
| $(ST_DIR)/obj/st_utest.o : st_utest.cpp $(ST_UTEST_DEPS) $(UTEST_DEPS) | ||||
| 	$(CXX) -c st_utest.cpp -o $@ \
 | ||||
| $(ST_DIR)/obj/%.o : %.cpp $(ST_UTEST_DEPS) $(UTEST_DEPS) | ||||
| 	$(CXX) -c $< -o $@ \
 | ||||
|         $(CXXFLAGS) $(UTEST_FLAGS) \
 | ||||
|         $(WARNFLAGS) \
 | ||||
|         -I$(GTEST_DIR)/include -I$(ST_UTEST) -I$(ST_DIR) -I$(ST_DIR)/obj | ||||
| 
 | ||||
| # generate the utest binary
 | ||||
| $(ST_DIR)/obj/st_utest : $(ST_DIR)/obj/st_utest.o $(ST_DIR)/obj/gtest.a $(ST_UTEST_DEPS) | ||||
| # Generate the utest binary
 | ||||
| $(ST_DIR)/obj/st_utest : $(OBJECTS) $(ST_DIR)/obj/gtest.a $(ST_UTEST_DEPS) | ||||
| 	$(CXX) -o $@ $(CXXFLAGS) $(UTEST_FLAGS) \
 | ||||
|         -lpthread -ldl $^ | ||||
|  |  | |||
							
								
								
									
										114
									
								
								trunk/3rdparty/st-srs/utest/st_utest.cpp
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										114
									
								
								trunk/3rdparty/st-srs/utest/st_utest.cpp
									
										
									
									
										vendored
									
									
								
							|  | @ -6,6 +6,14 @@ | |||
| #include <st.h> | ||||
| #include <assert.h> | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& out, const ErrorObject* err) { | ||||
|     if (!err) return out; | ||||
|     if (err->r0_) out << "r0=" << err->r0_; | ||||
|     if (err->errno_) out << ", errno=" << err->errno_; | ||||
|     if (!err->message_.empty()) out << ", msg=" << err->message_; | ||||
|     return out; | ||||
| } | ||||
| 
 | ||||
| // We could do something in the main of utest.
 | ||||
| // Copy from gtest-1.6.0/src/gtest_main.cc
 | ||||
| GTEST_API_ int main(int argc, char **argv) { | ||||
|  | @ -25,7 +33,7 @@ GTEST_API_ int main(int argc, char **argv) { | |||
| } | ||||
| 
 | ||||
| // basic test and samples.
 | ||||
| VOID TEST(SampleTest, FastSampleInt64Test) | ||||
| VOID TEST(SampleTest, ExampleIntSizeTest) | ||||
| { | ||||
|     EXPECT_EQ(1, (int)sizeof(int8_t)); | ||||
|     EXPECT_EQ(2, (int)sizeof(int16_t)); | ||||
|  | @ -33,107 +41,3 @@ VOID TEST(SampleTest, FastSampleInt64Test) | |||
|     EXPECT_EQ(8, (int)sizeof(int64_t)); | ||||
| } | ||||
| 
 | ||||
| void* pfn_coroutine(void* /*arg*/) | ||||
| { | ||||
|     st_usleep(0); | ||||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| VOID TEST(SampleTest, StartCoroutine) | ||||
| { | ||||
|     st_thread_t trd = st_thread_create(pfn_coroutine, NULL, 1, 0); | ||||
|     EXPECT_TRUE(trd != NULL); | ||||
| 
 | ||||
|     // Wait for joinable coroutine to quit.
 | ||||
|     st_thread_join(trd, NULL); | ||||
| } | ||||
| 
 | ||||
| VOID TEST(SampleTest, StartCoroutineX3) | ||||
| { | ||||
|     st_thread_t trd0 = st_thread_create(pfn_coroutine, NULL, 1, 0); | ||||
|     st_thread_t trd1 = st_thread_create(pfn_coroutine, NULL, 1, 0); | ||||
|     st_thread_t trd2 = st_thread_create(pfn_coroutine, NULL, 1, 0); | ||||
|     EXPECT_TRUE(trd0 != NULL && trd1 != NULL && trd2 != NULL); | ||||
| 
 | ||||
|     // Wait for joinable coroutine to quit.
 | ||||
|     st_thread_join(trd1, NULL); | ||||
|     st_thread_join(trd2, NULL); | ||||
|     st_thread_join(trd0, NULL); | ||||
| } | ||||
| 
 | ||||
| void* pfn_coroutine_add(void* arg) | ||||
| { | ||||
|     int v = 0; | ||||
|     int* pi = (int*)arg; | ||||
| 
 | ||||
|     // Load the change of arg.
 | ||||
|     while (v != *pi) { | ||||
|         v = *pi; | ||||
|         st_usleep(0); | ||||
|     } | ||||
| 
 | ||||
|     // Add with const.
 | ||||
|     v += 100; | ||||
|     *pi = v; | ||||
| 
 | ||||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| VOID TEST(SampleTest, StartCoroutineAdd) | ||||
| { | ||||
|     int v = 0; | ||||
|     st_thread_t trd = st_thread_create(pfn_coroutine_add, &v, 1, 0); | ||||
|     EXPECT_TRUE(trd != NULL); | ||||
| 
 | ||||
|     // Wait for joinable coroutine to quit.
 | ||||
|     st_thread_join(trd, NULL); | ||||
| 
 | ||||
|     EXPECT_EQ(100, v); | ||||
| } | ||||
| 
 | ||||
| VOID TEST(SampleTest, StartCoroutineAddX3) | ||||
| { | ||||
|     int v = 0; | ||||
|     st_thread_t trd0 = st_thread_create(pfn_coroutine_add, &v, 1, 0); | ||||
|     st_thread_t trd1 = st_thread_create(pfn_coroutine_add, &v, 1, 0); | ||||
|     st_thread_t trd2 = st_thread_create(pfn_coroutine_add, &v, 1, 0); | ||||
|     EXPECT_TRUE(trd0 != NULL && trd1 != NULL && trd2 != NULL); | ||||
| 
 | ||||
|     // Wait for joinable coroutine to quit.
 | ||||
|     st_thread_join(trd0, NULL); | ||||
|     st_thread_join(trd1, NULL); | ||||
|     st_thread_join(trd2, NULL); | ||||
| 
 | ||||
|     EXPECT_EQ(300, v); | ||||
| } | ||||
| 
 | ||||
| int pfn_coroutine_params_x4(int a, int b, int c, int d) | ||||
| { | ||||
|     int e = 0; | ||||
| 
 | ||||
|     st_usleep(0); | ||||
| 
 | ||||
|     e += a + b + c + d; | ||||
|     e += 100; | ||||
|     return e; | ||||
| } | ||||
| 
 | ||||
| void* pfn_coroutine_params(void* arg) | ||||
| { | ||||
|     int r0 = pfn_coroutine_params_x4(1, 2, 3, 4); | ||||
|     *(int*)arg = r0; | ||||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| VOID TEST(SampleTest, StartCoroutineParams) | ||||
| { | ||||
|     int r0 = 0; | ||||
|     st_thread_t trd = st_thread_create(pfn_coroutine_params, &r0, 1, 0); | ||||
|     EXPECT_TRUE(trd != NULL); | ||||
| 
 | ||||
|     // Wait for joinable coroutine to quit.
 | ||||
|     st_thread_join(trd, NULL); | ||||
| 
 | ||||
|     EXPECT_EQ(110, r0); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										111
									
								
								trunk/3rdparty/st-srs/utest/st_utest.hpp
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										111
									
								
								trunk/3rdparty/st-srs/utest/st_utest.hpp
									
										
									
									
										vendored
									
									
								
							|  | @ -10,7 +10,118 @@ | |||
| // @see https://stackoverflow.com/questions/47839718/sstream-redeclared-with-public-access-compiler-error
 | ||||
| #include <gtest/gtest.h> | ||||
| 
 | ||||
| #include <st.h> | ||||
| #include <string> | ||||
| 
 | ||||
| #define VOID | ||||
| 
 | ||||
| // Close the fd automatically.
 | ||||
| #define StFdCleanup(fd, stfd) impl__StFdCleanup _ST_free_##fd(&fd, &stfd) | ||||
| #define StStfdCleanup(stfd) impl__StFdCleanup _ST_free_##stfd(NULL, &stfd) | ||||
| class impl__StFdCleanup { | ||||
|     int* fd_; | ||||
|     st_netfd_t* stfd_; | ||||
| public: | ||||
|     impl__StFdCleanup(int* fd, st_netfd_t* stfd) : fd_(fd), stfd_(stfd) { | ||||
|     } | ||||
|     virtual ~impl__StFdCleanup() { | ||||
|         if (stfd_ && *stfd_) { | ||||
|             st_netfd_close(*stfd_); | ||||
|         } else if (fd_ && *fd_ > 0) { | ||||
|             ::close(*fd_); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| // For coroutine function to return with error object.
 | ||||
| struct ErrorObject { | ||||
|     int r0_; | ||||
|     int errno_; | ||||
|     std::string message_; | ||||
| 
 | ||||
|     ErrorObject(int r0, std::string message) : r0_(r0), errno_(errno), message_(message) { | ||||
|     } | ||||
| }; | ||||
| extern std::ostream& operator<<(std::ostream& out, const ErrorObject* err); | ||||
| #define ST_ASSERT_ERROR(error, r0, message) if (error) return new ErrorObject(r0, message) | ||||
| #define ST_COROUTINE_JOIN(trd, r0) ErrorObject* r0 = NULL; SrsAutoFree(ErrorObject, r0); if (trd) st_thread_join(trd, (void**)&r0) | ||||
| #define ST_EXPECT_SUCCESS(r0) EXPECT_TRUE(!r0) << r0 | ||||
| #define ST_EXPECT_FAILED(r0) EXPECT_TRUE(r0) << r0 | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| // To free the instance in the current scope, for instance, MyClass* ptr,
 | ||||
| // which is a ptr and this class will:
 | ||||
| //       1. free the ptr.
 | ||||
| //       2. set ptr to NULL.
 | ||||
| //
 | ||||
| // Usage:
 | ||||
| //       MyClass* po = new MyClass();
 | ||||
| //       // ...... use po
 | ||||
| //       SrsAutoFree(MyClass, po);
 | ||||
| //
 | ||||
| // Usage for array:
 | ||||
| //      MyClass** pa = new MyClass*[size];
 | ||||
| //      // ....... use pa
 | ||||
| //      SrsAutoFreeA(MyClass*, pa);
 | ||||
| //
 | ||||
| // @remark the MyClass can be basic type, for instance, SrsAutoFreeA(char, pstr),
 | ||||
| //      where the char* pstr = new char[size].
 | ||||
| // To delete object.
 | ||||
| #define SrsAutoFree(className, instance) \ | ||||
|     impl_SrsAutoFree<className> _auto_free_##instance(&instance, false, false, NULL) | ||||
| // To delete array.
 | ||||
| #define SrsAutoFreeA(className, instance) \ | ||||
|     impl_SrsAutoFree<className> _auto_free_array_##instance(&instance, true, false, NULL) | ||||
| // Use free instead of delete.
 | ||||
| #define SrsAutoFreeF(className, instance) \ | ||||
|     impl_SrsAutoFree<className> _auto_free_##instance(&instance, false, true, NULL) | ||||
| // Use hook instead of delete.
 | ||||
| #define SrsAutoFreeH(className, instance, hook) \ | ||||
|     impl_SrsAutoFree<className> _auto_free_##instance(&instance, false, false, hook) | ||||
| // The template implementation.
 | ||||
| template<class T> | ||||
| class impl_SrsAutoFree | ||||
| { | ||||
| private: | ||||
|     T** ptr; | ||||
|     bool is_array; | ||||
|     bool _use_free; | ||||
|     void (*_hook)(T*); | ||||
| public: | ||||
|     // If use_free, use free(void*) to release the p.
 | ||||
|     // If specified hook, use hook(p) to release it.
 | ||||
|     // Use delete to release p, or delete[] if p is an array.
 | ||||
|     impl_SrsAutoFree(T** p, bool array, bool use_free, void (*hook)(T*)) { | ||||
|         ptr = p; | ||||
|         is_array = array; | ||||
|         _use_free = use_free; | ||||
|         _hook = hook; | ||||
|     } | ||||
| 
 | ||||
|     virtual ~impl_SrsAutoFree() { | ||||
|         if (ptr == NULL || *ptr == NULL) { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         if (_use_free) { | ||||
|             free(*ptr); | ||||
|         } else if (_hook) { | ||||
|             _hook(*ptr); | ||||
|         } else { | ||||
|             if (is_array) { | ||||
|                 delete[] *ptr; | ||||
|             } else { | ||||
|                 delete *ptr; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         *ptr = NULL; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| // The time unit in ms, for example 100 * SRS_UTIME_MILLISECONDS means 100ms.
 | ||||
| #define SRS_UTIME_MILLISECONDS 1000 | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										120
									
								
								trunk/3rdparty/st-srs/utest/st_utest_coroutines.cpp
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								trunk/3rdparty/st-srs/utest/st_utest_coroutines.cpp
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,120 @@ | |||
| /* SPDX-License-Identifier: MIT */ | ||||
| /* Copyright (c) 2021 Winlin */ | ||||
| 
 | ||||
| #include <st_utest.hpp> | ||||
| 
 | ||||
| #include <st.h> | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // The utest for empty coroutine.
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| void* coroutine(void* /*arg*/) | ||||
| { | ||||
|     st_usleep(0); | ||||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| VOID TEST(CoroutineTest, StartCoroutine) | ||||
| { | ||||
|     st_thread_t trd = st_thread_create(coroutine, NULL, 1, 0); | ||||
|     EXPECT_TRUE(trd != NULL); | ||||
| 
 | ||||
|     // Wait for joinable coroutine to quit.
 | ||||
|     st_thread_join(trd, NULL); | ||||
| } | ||||
| 
 | ||||
| VOID TEST(CoroutineTest, StartCoroutineX3) | ||||
| { | ||||
|     st_thread_t trd0 = st_thread_create(coroutine, NULL, 1, 0); | ||||
|     st_thread_t trd1 = st_thread_create(coroutine, NULL, 1, 0); | ||||
|     st_thread_t trd2 = st_thread_create(coroutine, NULL, 1, 0); | ||||
|     EXPECT_TRUE(trd0 != NULL && trd1 != NULL && trd2 != NULL); | ||||
| 
 | ||||
|     // Wait for joinable coroutine to quit.
 | ||||
|     st_thread_join(trd1, NULL); | ||||
|     st_thread_join(trd2, NULL); | ||||
|     st_thread_join(trd0, NULL); | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // The utest for adding coroutine.
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| void* coroutine_add(void* arg) | ||||
| { | ||||
|     int v = 0; | ||||
|     int* pi = (int*)arg; | ||||
| 
 | ||||
|     // Load the change of arg.
 | ||||
|     while (v != *pi) { | ||||
|         v = *pi; | ||||
|         st_usleep(0); | ||||
|     } | ||||
| 
 | ||||
|     // Add with const.
 | ||||
|     v += 100; | ||||
|     *pi = v; | ||||
| 
 | ||||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| VOID TEST(CoroutineTest, StartCoroutineAdd) | ||||
| { | ||||
|     int v = 0; | ||||
|     st_thread_t trd = st_thread_create(coroutine_add, &v, 1, 0); | ||||
|     EXPECT_TRUE(trd != NULL); | ||||
| 
 | ||||
|     // Wait for joinable coroutine to quit.
 | ||||
|     st_thread_join(trd, NULL); | ||||
| 
 | ||||
|     EXPECT_EQ(100, v); | ||||
| } | ||||
| 
 | ||||
| VOID TEST(CoroutineTest, StartCoroutineAddX3) | ||||
| { | ||||
|     int v = 0; | ||||
|     st_thread_t trd0 = st_thread_create(coroutine_add, &v, 1, 0); | ||||
|     st_thread_t trd1 = st_thread_create(coroutine_add, &v, 1, 0); | ||||
|     st_thread_t trd2 = st_thread_create(coroutine_add, &v, 1, 0); | ||||
|     EXPECT_TRUE(trd0 != NULL && trd1 != NULL && trd2 != NULL); | ||||
| 
 | ||||
|     // Wait for joinable coroutine to quit.
 | ||||
|     st_thread_join(trd0, NULL); | ||||
|     st_thread_join(trd1, NULL); | ||||
|     st_thread_join(trd2, NULL); | ||||
| 
 | ||||
|     EXPECT_EQ(300, v); | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // The utest for output params coroutine.
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| int coroutine_params_x4(int a, int b, int c, int d) | ||||
| { | ||||
|     int e = 0; | ||||
| 
 | ||||
|     st_usleep(0); | ||||
| 
 | ||||
|     e += a + b + c + d; | ||||
|     e += 100; | ||||
|     return e; | ||||
| } | ||||
| 
 | ||||
| void* coroutine_params(void* arg) | ||||
| { | ||||
|     int r0 = coroutine_params_x4(1, 2, 3, 4); | ||||
|     *(int*)arg = r0; | ||||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| VOID TEST(CoroutineTest, StartCoroutineParams) | ||||
| { | ||||
|     int r0 = 0; | ||||
|     st_thread_t trd = st_thread_create(coroutine_params, &r0, 1, 0); | ||||
|     EXPECT_TRUE(trd != NULL); | ||||
| 
 | ||||
|     // Wait for joinable coroutine to quit.
 | ||||
|     st_thread_join(trd, NULL); | ||||
| 
 | ||||
|     EXPECT_EQ(110, r0); | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										92
									
								
								trunk/3rdparty/st-srs/utest/st_utest_tcp.cpp
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								trunk/3rdparty/st-srs/utest/st_utest_tcp.cpp
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,92 @@ | |||
| /* SPDX-License-Identifier: MIT */ | ||||
| /* Copyright (c) 2021 Winlin */ | ||||
| 
 | ||||
| #include <st_utest.hpp> | ||||
| 
 | ||||
| #include <st.h> | ||||
| #include <assert.h> | ||||
| 
 | ||||
| #include <sys/socket.h> | ||||
| #include <netinet/in.h> | ||||
| #include <arpa/inet.h> | ||||
| 
 | ||||
| #define ST_UTEST_PORT 26878 | ||||
| #define ST_UTEST_TIMEOUT (100 * SRS_UTIME_MILLISECONDS) | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // The utest for ping-pong TCP server coroutine.
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| void* tcp_server(void* /*arg*/) | ||||
| { | ||||
|     int fd = -1; | ||||
|     st_netfd_t stfd = NULL; | ||||
|     StFdCleanup(fd, stfd); | ||||
| 
 | ||||
|     fd = socket(AF_INET, SOCK_STREAM, 0); | ||||
|     ST_ASSERT_ERROR(fd == -1, fd, "Create socket"); | ||||
| 
 | ||||
|     struct sockaddr_in addr; | ||||
|     addr.sin_family = AF_INET; | ||||
|     addr.sin_addr.s_addr = htonl(INADDR_ANY); | ||||
|     addr.sin_port = htons(ST_UTEST_PORT); | ||||
| 
 | ||||
|     int v = 1; | ||||
|     int r0 = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &v, sizeof(int)); | ||||
|     ST_ASSERT_ERROR(r0, r0, "Set SO_REUSEADDR"); | ||||
| 
 | ||||
|     r0 = ::bind(fd, (const sockaddr*)&addr, sizeof(addr)); | ||||
|     ST_ASSERT_ERROR(r0, r0, "Bind socket"); | ||||
| 
 | ||||
|     r0 = ::listen(fd, 10); | ||||
|     ST_ASSERT_ERROR(r0, r0, "Listen socket"); | ||||
| 
 | ||||
|     stfd = st_netfd_open_socket(fd); | ||||
|     ST_ASSERT_ERROR(!stfd, fd, "Open ST socket"); | ||||
| 
 | ||||
|     st_netfd_t client = NULL; | ||||
|     StStfdCleanup(client); | ||||
| 
 | ||||
|     client = st_accept(stfd, NULL, NULL, ST_UTEST_TIMEOUT); | ||||
|     ST_ASSERT_ERROR(!client, fd, "Accept client"); | ||||
| 
 | ||||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| void* tcp_client(void* /*arg*/) | ||||
| { | ||||
|     int fd = -1; | ||||
|     st_netfd_t stfd = NULL; | ||||
|     StFdCleanup(fd, stfd); | ||||
| 
 | ||||
|     fd = socket(AF_INET, SOCK_STREAM, 0); | ||||
|     ST_ASSERT_ERROR(fd == -1, fd, "Create socket"); | ||||
| 
 | ||||
|     struct sockaddr_in addr; | ||||
|     addr.sin_family = AF_INET; | ||||
|     addr.sin_addr.s_addr = inet_addr("127.0.0.1"); | ||||
|     addr.sin_port = htons(ST_UTEST_PORT); | ||||
| 
 | ||||
|     stfd = st_netfd_open_socket(fd); | ||||
|     ST_ASSERT_ERROR(!stfd, fd, "Open ST socket"); | ||||
| 
 | ||||
|     int r0 = st_connect(stfd, (const sockaddr*)&addr, sizeof(addr), ST_UTEST_TIMEOUT); | ||||
|     ST_ASSERT_ERROR(r0, r0, "Connect to server"); | ||||
| 
 | ||||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| VOID TEST(TcpTest, TcpConnection) | ||||
| { | ||||
|     st_thread_t svr = st_thread_create(tcp_server, NULL, 1, 0); | ||||
|     EXPECT_TRUE(svr != NULL); | ||||
| 
 | ||||
|     st_thread_t client = st_thread_create(tcp_client, NULL, 1, 0); | ||||
|     EXPECT_TRUE(client != NULL); | ||||
| 
 | ||||
|     ST_COROUTINE_JOIN(svr, r0); | ||||
|     ST_COROUTINE_JOIN(client, r1); | ||||
| 
 | ||||
|     ST_EXPECT_SUCCESS(r0); | ||||
|     ST_EXPECT_SUCCESS(r1); | ||||
| } | ||||
| 
 | ||||
|  | @ -6,6 +6,7 @@ The changelog for SRS. | |||
| 
 | ||||
| ## SRS 5.0 Changelog | ||||
| 
 | ||||
| * v5.0, 2022-08-06, Support MIPS 64bits for loongson 3A4000/3B3000. v5.0.34 | ||||
| * v5.0, 2022-06-29, Support multiple threads by thread pool. v5.0.32 | ||||
| * v5.0, 2022-06-28, ST: Support thread-local for multiple threads. v5.0.31 | ||||
| * v5.0, 2022-06-17, Merge [#3010](https://github.com/ossrs/srs/pull/3010): SRT: Support Coroutine Native SRT over ST. (#3010). v5.0.30 | ||||
|  |  | |||
|  | @ -9,6 +9,6 @@ | |||
| 
 | ||||
| #define VERSION_MAJOR       5 | ||||
| #define VERSION_MINOR       0 | ||||
| #define VERSION_REVISION    33 | ||||
| #define VERSION_REVISION    34 | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue