正在显示
6 个修改的文件
包含
329 行增加
和
128 行删除
| @@ -485,6 +485,7 @@ Supported operating systems and hardware: | @@ -485,6 +485,7 @@ Supported operating systems and hardware: | ||
| 485 | * 2013-10-17, Created.<br/> | 485 | * 2013-10-17, Created.<br/> |
| 486 | 486 | ||
| 487 | ## History | 487 | ## History |
| 488 | +* v2.0, 2014-12-02, srs-librtmp support hijack io apis for st-load. 2.0.42. | ||
| 488 | * v2.0, 2014-12-01, for [#237](https://github.com/winlinvip/simple-rtmp-server/issues/237), refine syscall for recv, supports 1.5k clients. 2.0.41. | 489 | * v2.0, 2014-12-01, for [#237](https://github.com/winlinvip/simple-rtmp-server/issues/237), refine syscall for recv, supports 1.5k clients. 2.0.41. |
| 489 | * v2.0, 2014-11-30, add qtcreate project file trunk/src/qt/srs/srs-qt.pro. 2.0.39. | 490 | * v2.0, 2014-11-30, add qtcreate project file trunk/src/qt/srs/srs-qt.pro. 2.0.39. |
| 490 | * v2.0, 2014-11-29, fix [#235](https://github.com/winlinvip/simple-rtmp-server/issues/235), refine handshake, replace union with template method. 2.0.38. | 491 | * v2.0, 2014-11-29, fix [#235](https://github.com/winlinvip/simple-rtmp-server/issues/235), refine handshake, replace union with template method. 2.0.38. |
| @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 31 | // current release version | 31 | // current release version |
| 32 | #define VERSION_MAJOR 2 | 32 | #define VERSION_MAJOR 2 |
| 33 | #define VERSION_MINOR 0 | 33 | #define VERSION_MINOR 0 |
| 34 | -#define VERSION_REVISION 41 | 34 | +#define VERSION_REVISION 42 |
| 35 | // server info. | 35 | // server info. |
| 36 | #define RTMP_SIG_SRS_KEY "SRS" | 36 | #define RTMP_SIG_SRS_KEY "SRS" |
| 37 | #define RTMP_SIG_SRS_ROLE "origin/edge server" | 37 | #define RTMP_SIG_SRS_ROLE "origin/edge server" |
| @@ -43,188 +43,305 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -43,188 +43,305 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 43 | #define ST_UTIME_NO_TIMEOUT -1 | 43 | #define ST_UTIME_NO_TIMEOUT -1 |
| 44 | #endif | 44 | #endif |
| 45 | 45 | ||
| 46 | +// when io not hijacked, use simple socket, the block sync stream. | ||
| 47 | +#ifndef SRS_HIJACK_IO | ||
| 48 | + struct SrsBlockSyncSocket | ||
| 49 | + { | ||
| 50 | + SOCKET fd; | ||
| 51 | + int64_t recv_timeout; | ||
| 52 | + int64_t send_timeout; | ||
| 53 | + int64_t recv_bytes; | ||
| 54 | + int64_t send_bytes; | ||
| 55 | + | ||
| 56 | + SrsBlockSyncSocket() { | ||
| 57 | + send_timeout = recv_timeout = ST_UTIME_NO_TIMEOUT; | ||
| 58 | + recv_bytes = send_bytes = 0; | ||
| 59 | + | ||
| 60 | + SOCKET_RESET(fd); | ||
| 61 | + SOCKET_SETUP(); | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + virtual ~SrsBlockSyncSocket() { | ||
| 65 | + SOCKET_CLOSE(fd); | ||
| 66 | + SOCKET_CLEANUP(); | ||
| 67 | + } | ||
| 68 | + }; | ||
| 69 | + srs_hijack_io_t srs_hijack_io_create() | ||
| 70 | + { | ||
| 71 | + SrsBlockSyncSocket* skt = new SrsBlockSyncSocket(); | ||
| 72 | + return skt; | ||
| 73 | + } | ||
| 74 | + void srs_hijack_io_destroy(srs_hijack_io_t ctx) | ||
| 75 | + { | ||
| 76 | + SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx; | ||
| 77 | + srs_freep(skt); | ||
| 78 | + } | ||
| 79 | + int srs_hijack_io_create_socket(srs_hijack_io_t ctx) | ||
| 80 | + { | ||
| 81 | + SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx; | ||
| 82 | + | ||
| 83 | + skt->fd = ::socket(AF_INET, SOCK_STREAM, 0); | ||
| 84 | + if (!SOCKET_VALID(skt->fd)) { | ||
| 85 | + return ERROR_SOCKET_CREATE; | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + return ERROR_SUCCESS; | ||
| 89 | + } | ||
| 90 | + int srs_hijack_io_connect(srs_hijack_io_t ctx, const char* server_ip, int port) | ||
| 91 | + { | ||
| 92 | + SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx; | ||
| 93 | + | ||
| 94 | + sockaddr_in addr; | ||
| 95 | + addr.sin_family = AF_INET; | ||
| 96 | + addr.sin_port = htons(port); | ||
| 97 | + addr.sin_addr.s_addr = inet_addr(server_ip); | ||
| 98 | + | ||
| 99 | + if(::connect(skt->fd, (const struct sockaddr*)&addr, sizeof(sockaddr_in)) < 0){ | ||
| 100 | + return ERROR_SOCKET_CONNECT; | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + return ERROR_SUCCESS; | ||
| 104 | + } | ||
| 105 | + int srs_hijack_io_read(srs_hijack_io_t ctx, void* buf, size_t size, ssize_t* nread) | ||
| 106 | + { | ||
| 107 | + SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx; | ||
| 108 | + | ||
| 109 | + int ret = ERROR_SUCCESS; | ||
| 110 | + | ||
| 111 | + ssize_t nb_read = ::recv(skt->fd, (char*)buf, size, 0); | ||
| 112 | + | ||
| 113 | + if (nread) { | ||
| 114 | + *nread = nb_read; | ||
| 115 | + } | ||
| 116 | + | ||
| 117 | + // On success a non-negative integer indicating the number of bytes actually read is returned | ||
| 118 | + // (a value of 0 means the network connection is closed or end of file is reached). | ||
| 119 | + if (nb_read <= 0) { | ||
| 120 | + if (nb_read < 0 && SOCKET_ERRNO() == SOCKET_ETIME) { | ||
| 121 | + return ERROR_SOCKET_TIMEOUT; | ||
| 122 | + } | ||
| 123 | + | ||
| 124 | + if (nb_read == 0) { | ||
| 125 | + errno = SOCKET_ECONNRESET; | ||
| 126 | + } | ||
| 127 | + | ||
| 128 | + return ERROR_SOCKET_READ; | ||
| 129 | + } | ||
| 130 | + | ||
| 131 | + skt->recv_bytes += nb_read; | ||
| 132 | + | ||
| 133 | + return ret; | ||
| 134 | + } | ||
| 135 | + void srs_hijack_io_set_recv_timeout(srs_hijack_io_t ctx, int64_t timeout_us) | ||
| 136 | + { | ||
| 137 | + SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx; | ||
| 138 | + skt->recv_timeout = timeout_us; | ||
| 139 | + } | ||
| 140 | + int64_t srs_hijack_io_get_recv_timeout(srs_hijack_io_t ctx) | ||
| 141 | + { | ||
| 142 | + SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx; | ||
| 143 | + return skt->recv_timeout; | ||
| 144 | + } | ||
| 145 | + int64_t srs_hijack_io_get_recv_bytes(srs_hijack_io_t ctx) | ||
| 146 | + { | ||
| 147 | + SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx; | ||
| 148 | + return skt->recv_bytes; | ||
| 149 | + } | ||
| 150 | + void srs_hijack_io_set_send_timeout(srs_hijack_io_t ctx, int64_t timeout_us) | ||
| 151 | + { | ||
| 152 | + SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx; | ||
| 153 | + skt->send_timeout = timeout_us; | ||
| 154 | + } | ||
| 155 | + int64_t srs_hijack_io_get_send_timeout(srs_hijack_io_t ctx) | ||
| 156 | + { | ||
| 157 | + SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx; | ||
| 158 | + return skt->send_timeout; | ||
| 159 | + } | ||
| 160 | + int64_t srs_hijack_io_get_send_bytes(srs_hijack_io_t ctx) | ||
| 161 | + { | ||
| 162 | + SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx; | ||
| 163 | + return skt->send_bytes; | ||
| 164 | + } | ||
| 165 | + int srs_hijack_io_writev(srs_hijack_io_t ctx, const iovec *iov, int iov_size, ssize_t* nwrite) | ||
| 166 | + { | ||
| 167 | + SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx; | ||
| 168 | + | ||
| 169 | + int ret = ERROR_SUCCESS; | ||
| 170 | + | ||
| 171 | + ssize_t nb_write = ::writev(skt->fd, iov, iov_size); | ||
| 172 | + | ||
| 173 | + if (nwrite) { | ||
| 174 | + *nwrite = nb_write; | ||
| 175 | + } | ||
| 176 | + | ||
| 177 | + // On success, the readv() function returns the number of bytes read; | ||
| 178 | + // the writev() function returns the number of bytes written. On error, -1 is | ||
| 179 | + // returned, and errno is set appropriately. | ||
| 180 | + if (nb_write <= 0) { | ||
| 181 | + // @see https://github.com/winlinvip/simple-rtmp-server/issues/200 | ||
| 182 | + if (nb_write < 0 && SOCKET_ERRNO() == SOCKET_ETIME) { | ||
| 183 | + return ERROR_SOCKET_TIMEOUT; | ||
| 184 | + } | ||
| 185 | + | ||
| 186 | + return ERROR_SOCKET_WRITE; | ||
| 187 | + } | ||
| 188 | + | ||
| 189 | + skt->send_bytes += nb_write; | ||
| 190 | + | ||
| 191 | + return ret; | ||
| 192 | + } | ||
| 193 | + bool srs_hijack_io_is_never_timeout(srs_hijack_io_t ctx, int64_t timeout_us) | ||
| 194 | + { | ||
| 195 | + return timeout_us == (int64_t)ST_UTIME_NO_TIMEOUT; | ||
| 196 | + } | ||
| 197 | + int srs_hijack_io_read_fully(srs_hijack_io_t ctx, void* buf, size_t size, ssize_t* nread) | ||
| 198 | + { | ||
| 199 | + SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx; | ||
| 200 | + | ||
| 201 | + int ret = ERROR_SUCCESS; | ||
| 202 | + | ||
| 203 | + size_t left = size; | ||
| 204 | + ssize_t nb_read = 0; | ||
| 205 | + | ||
| 206 | + while (left > 0) { | ||
| 207 | + char* this_buf = (char*)buf + nb_read; | ||
| 208 | + ssize_t this_nread; | ||
| 209 | + | ||
| 210 | + if ((ret = srs_hijack_io_read(ctx, this_buf, left, &this_nread)) != ERROR_SUCCESS) { | ||
| 211 | + return ret; | ||
| 212 | + } | ||
| 213 | + | ||
| 214 | + nb_read += this_nread; | ||
| 215 | + left -= (size_t)this_nread; | ||
| 216 | + } | ||
| 217 | + | ||
| 218 | + if (nread) { | ||
| 219 | + *nread = nb_read; | ||
| 220 | + } | ||
| 221 | + skt->recv_bytes += nb_read; | ||
| 222 | + | ||
| 223 | + return ret; | ||
| 224 | + } | ||
| 225 | + int srs_hijack_io_write(srs_hijack_io_t ctx, void* buf, size_t size, ssize_t* nwrite) | ||
| 226 | + { | ||
| 227 | + SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx; | ||
| 228 | + | ||
| 229 | + int ret = ERROR_SUCCESS; | ||
| 230 | + | ||
| 231 | + ssize_t nb_write = ::send(skt->fd, (char*)buf, size, 0); | ||
| 232 | + | ||
| 233 | + if (nwrite) { | ||
| 234 | + *nwrite = nb_write; | ||
| 235 | + } | ||
| 236 | + | ||
| 237 | + if (nb_write <= 0) { | ||
| 238 | + // @see https://github.com/winlinvip/simple-rtmp-server/issues/200 | ||
| 239 | + if (nb_write < 0 && SOCKET_ERRNO() == SOCKET_ETIME) { | ||
| 240 | + return ERROR_SOCKET_TIMEOUT; | ||
| 241 | + } | ||
| 242 | + | ||
| 243 | + return ERROR_SOCKET_WRITE; | ||
| 244 | + } | ||
| 245 | + | ||
| 246 | + skt->send_bytes += nb_write; | ||
| 247 | + | ||
| 248 | + return ret; | ||
| 249 | + } | ||
| 250 | +#endif | ||
| 251 | + | ||
| 46 | SimpleSocketStream::SimpleSocketStream() | 252 | SimpleSocketStream::SimpleSocketStream() |
| 47 | { | 253 | { |
| 48 | - SOCKET_RESET(fd); | ||
| 49 | - send_timeout = recv_timeout = ST_UTIME_NO_TIMEOUT; | ||
| 50 | - recv_bytes = send_bytes = 0; | ||
| 51 | - SOCKET_SETUP(); | 254 | + io = srs_hijack_io_create(); |
| 52 | } | 255 | } |
| 53 | 256 | ||
| 54 | SimpleSocketStream::~SimpleSocketStream() | 257 | SimpleSocketStream::~SimpleSocketStream() |
| 55 | { | 258 | { |
| 56 | - SOCKET_CLOSE(fd); | ||
| 57 | - SOCKET_CLEANUP(); | 259 | + if (io) { |
| 260 | + srs_hijack_io_destroy(io); | ||
| 261 | + io = NULL; | ||
| 262 | + } | ||
| 58 | } | 263 | } |
| 59 | 264 | ||
| 60 | int SimpleSocketStream::create_socket() | 265 | int SimpleSocketStream::create_socket() |
| 61 | { | 266 | { |
| 62 | - fd = ::socket(AF_INET, SOCK_STREAM, 0); | ||
| 63 | - if (!SOCKET_VALID(fd)) { | ||
| 64 | - return ERROR_SOCKET_CREATE; | ||
| 65 | - } | ||
| 66 | - | ||
| 67 | - return ERROR_SUCCESS; | 267 | + srs_assert(io); |
| 268 | + return srs_hijack_io_create_socket(io); | ||
| 68 | } | 269 | } |
| 69 | 270 | ||
| 70 | int SimpleSocketStream::connect(const char* server_ip, int port) | 271 | int SimpleSocketStream::connect(const char* server_ip, int port) |
| 71 | { | 272 | { |
| 72 | - sockaddr_in addr; | ||
| 73 | - addr.sin_family = AF_INET; | ||
| 74 | - addr.sin_port = htons(port); | ||
| 75 | - addr.sin_addr.s_addr = inet_addr(server_ip); | ||
| 76 | - | ||
| 77 | - if(::connect(fd, (const struct sockaddr*)&addr, sizeof(sockaddr_in)) < 0){ | ||
| 78 | - return ERROR_SOCKET_CONNECT; | ||
| 79 | - } | ||
| 80 | - | ||
| 81 | - return ERROR_SUCCESS; | 273 | + srs_assert(io); |
| 274 | + return srs_hijack_io_connect(io, server_ip, port); | ||
| 82 | } | 275 | } |
| 83 | 276 | ||
| 84 | // ISrsBufferReader | 277 | // ISrsBufferReader |
| 85 | int SimpleSocketStream::read(void* buf, size_t size, ssize_t* nread) | 278 | int SimpleSocketStream::read(void* buf, size_t size, ssize_t* nread) |
| 86 | { | 279 | { |
| 87 | - int ret = ERROR_SUCCESS; | ||
| 88 | - | ||
| 89 | - ssize_t nb_read = ::recv(fd, (char*)buf, size, 0); | ||
| 90 | - | ||
| 91 | - if (nread) { | ||
| 92 | - *nread = nb_read; | ||
| 93 | - } | ||
| 94 | - | ||
| 95 | - // On success a non-negative integer indicating the number of bytes actually read is returned | ||
| 96 | - // (a value of 0 means the network connection is closed or end of file is reached). | ||
| 97 | - if (nb_read <= 0) { | ||
| 98 | - if (nb_read < 0 && SOCKET_ERRNO() == SOCKET_ETIME) { | ||
| 99 | - return ERROR_SOCKET_TIMEOUT; | ||
| 100 | - } | ||
| 101 | - | ||
| 102 | - if (nb_read == 0) { | ||
| 103 | - errno = SOCKET_ECONNRESET; | ||
| 104 | - } | ||
| 105 | - | ||
| 106 | - return ERROR_SOCKET_READ; | ||
| 107 | - } | ||
| 108 | - | ||
| 109 | - recv_bytes += nb_read; | ||
| 110 | - | ||
| 111 | - return ret; | 280 | + srs_assert(io); |
| 281 | + return srs_hijack_io_read(io, buf, size, nread); | ||
| 112 | } | 282 | } |
| 113 | 283 | ||
| 114 | // ISrsProtocolReader | 284 | // ISrsProtocolReader |
| 115 | void SimpleSocketStream::set_recv_timeout(int64_t timeout_us) | 285 | void SimpleSocketStream::set_recv_timeout(int64_t timeout_us) |
| 116 | { | 286 | { |
| 117 | - recv_timeout = timeout_us; | 287 | + srs_assert(io); |
| 288 | + srs_hijack_io_set_recv_timeout(io, timeout_us); | ||
| 118 | } | 289 | } |
| 119 | 290 | ||
| 120 | int64_t SimpleSocketStream::get_recv_timeout() | 291 | int64_t SimpleSocketStream::get_recv_timeout() |
| 121 | { | 292 | { |
| 122 | - return recv_timeout; | 293 | + srs_assert(io); |
| 294 | + return srs_hijack_io_get_recv_timeout(io); | ||
| 123 | } | 295 | } |
| 124 | 296 | ||
| 125 | int64_t SimpleSocketStream::get_recv_bytes() | 297 | int64_t SimpleSocketStream::get_recv_bytes() |
| 126 | { | 298 | { |
| 127 | - return recv_bytes; | 299 | + srs_assert(io); |
| 300 | + return srs_hijack_io_get_recv_bytes(io); | ||
| 128 | } | 301 | } |
| 129 | 302 | ||
| 130 | // ISrsProtocolWriter | 303 | // ISrsProtocolWriter |
| 131 | void SimpleSocketStream::set_send_timeout(int64_t timeout_us) | 304 | void SimpleSocketStream::set_send_timeout(int64_t timeout_us) |
| 132 | { | 305 | { |
| 133 | - send_timeout = timeout_us; | 306 | + srs_assert(io); |
| 307 | + srs_hijack_io_set_send_timeout(io, timeout_us); | ||
| 134 | } | 308 | } |
| 135 | 309 | ||
| 136 | int64_t SimpleSocketStream::get_send_timeout() | 310 | int64_t SimpleSocketStream::get_send_timeout() |
| 137 | { | 311 | { |
| 138 | - return send_timeout; | 312 | + srs_assert(io); |
| 313 | + return srs_hijack_io_get_send_timeout(io); | ||
| 139 | } | 314 | } |
| 140 | 315 | ||
| 141 | int64_t SimpleSocketStream::get_send_bytes() | 316 | int64_t SimpleSocketStream::get_send_bytes() |
| 142 | { | 317 | { |
| 143 | - return send_bytes; | 318 | + srs_assert(io); |
| 319 | + return srs_hijack_io_get_send_bytes(io); | ||
| 144 | } | 320 | } |
| 145 | 321 | ||
| 146 | int SimpleSocketStream::writev(const iovec *iov, int iov_size, ssize_t* nwrite) | 322 | int SimpleSocketStream::writev(const iovec *iov, int iov_size, ssize_t* nwrite) |
| 147 | { | 323 | { |
| 148 | - int ret = ERROR_SUCCESS; | ||
| 149 | - | ||
| 150 | - ssize_t nb_write = ::writev(fd, iov, iov_size); | ||
| 151 | - | ||
| 152 | - if (nwrite) { | ||
| 153 | - *nwrite = nb_write; | ||
| 154 | - } | ||
| 155 | - | ||
| 156 | - // On success, the readv() function returns the number of bytes read; | ||
| 157 | - // the writev() function returns the number of bytes written. On error, -1 is | ||
| 158 | - // returned, and errno is set appropriately. | ||
| 159 | - if (nb_write <= 0) { | ||
| 160 | - // @see https://github.com/winlinvip/simple-rtmp-server/issues/200 | ||
| 161 | - if (nb_write < 0 && SOCKET_ERRNO() == SOCKET_ETIME) { | ||
| 162 | - return ERROR_SOCKET_TIMEOUT; | ||
| 163 | - } | ||
| 164 | - | ||
| 165 | - return ERROR_SOCKET_WRITE; | ||
| 166 | - } | ||
| 167 | - | ||
| 168 | - send_bytes += nb_write; | ||
| 169 | - | ||
| 170 | - return ret; | 324 | + srs_assert(io); |
| 325 | + return srs_hijack_io_writev(io, iov, iov_size, nwrite); | ||
| 171 | } | 326 | } |
| 172 | 327 | ||
| 173 | // ISrsProtocolReaderWriter | 328 | // ISrsProtocolReaderWriter |
| 174 | bool SimpleSocketStream::is_never_timeout(int64_t timeout_us) | 329 | bool SimpleSocketStream::is_never_timeout(int64_t timeout_us) |
| 175 | { | 330 | { |
| 176 | - return timeout_us == (int64_t)ST_UTIME_NO_TIMEOUT; | 331 | + srs_assert(io); |
| 332 | + return srs_hijack_io_is_never_timeout(io, timeout_us); | ||
| 177 | } | 333 | } |
| 178 | 334 | ||
| 179 | int SimpleSocketStream::read_fully(void* buf, size_t size, ssize_t* nread) | 335 | int SimpleSocketStream::read_fully(void* buf, size_t size, ssize_t* nread) |
| 180 | { | 336 | { |
| 181 | - int ret = ERROR_SUCCESS; | ||
| 182 | - | ||
| 183 | - size_t left = size; | ||
| 184 | - ssize_t nb_read = 0; | ||
| 185 | - | ||
| 186 | - while (left > 0) { | ||
| 187 | - char* this_buf = (char*)buf + nb_read; | ||
| 188 | - ssize_t this_nread; | ||
| 189 | - | ||
| 190 | - if ((ret = this->read(this_buf, left, &this_nread)) != ERROR_SUCCESS) { | ||
| 191 | - return ret; | ||
| 192 | - } | ||
| 193 | - | ||
| 194 | - nb_read += this_nread; | ||
| 195 | - left -= (size_t)this_nread; | ||
| 196 | - } | ||
| 197 | - | ||
| 198 | - if (nread) { | ||
| 199 | - *nread = nb_read; | ||
| 200 | - } | ||
| 201 | - recv_bytes += nb_read; | ||
| 202 | - | ||
| 203 | - return ret; | 337 | + srs_assert(io); |
| 338 | + return srs_hijack_io_read_fully(io, buf, size, nread); | ||
| 204 | } | 339 | } |
| 205 | 340 | ||
| 206 | int SimpleSocketStream::write(void* buf, size_t size, ssize_t* nwrite) | 341 | int SimpleSocketStream::write(void* buf, size_t size, ssize_t* nwrite) |
| 207 | { | 342 | { |
| 208 | - int ret = ERROR_SUCCESS; | ||
| 209 | - | ||
| 210 | - ssize_t nb_write = ::send(fd, (char*)buf, size, 0); | ||
| 211 | - | ||
| 212 | - if (nwrite) { | ||
| 213 | - *nwrite = nb_write; | ||
| 214 | - } | ||
| 215 | - | ||
| 216 | - if (nb_write <= 0) { | ||
| 217 | - // @see https://github.com/winlinvip/simple-rtmp-server/issues/200 | ||
| 218 | - if (nb_write < 0 && SOCKET_ERRNO() == SOCKET_ETIME) { | ||
| 219 | - return ERROR_SOCKET_TIMEOUT; | ||
| 220 | - } | ||
| 221 | - | ||
| 222 | - return ERROR_SOCKET_WRITE; | ||
| 223 | - } | ||
| 224 | - | ||
| 225 | - send_bytes += nb_write; | ||
| 226 | - | ||
| 227 | - return ret; | 343 | + srs_assert(io); |
| 344 | + return srs_hijack_io_write(io, buf, size, nwrite); | ||
| 228 | } | 345 | } |
| 229 | 346 | ||
| 230 | 347 |
| @@ -32,7 +32,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -32,7 +32,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 32 | 32 | ||
| 33 | #include <srs_protocol_io.hpp> | 33 | #include <srs_protocol_io.hpp> |
| 34 | #include <srs_librtmp.hpp> | 34 | #include <srs_librtmp.hpp> |
| 35 | - | 35 | + |
| 36 | /** | 36 | /** |
| 37 | * simple socket stream, | 37 | * simple socket stream, |
| 38 | * use tcp socket, sync block mode, for client like srs-librtmp. | 38 | * use tcp socket, sync block mode, for client like srs-librtmp. |
| @@ -40,11 +40,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -40,11 +40,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 40 | class SimpleSocketStream : public ISrsProtocolReaderWriter | 40 | class SimpleSocketStream : public ISrsProtocolReaderWriter |
| 41 | { | 41 | { |
| 42 | private: | 42 | private: |
| 43 | - int64_t recv_timeout; | ||
| 44 | - int64_t send_timeout; | ||
| 45 | - int64_t recv_bytes; | ||
| 46 | - int64_t send_bytes; | ||
| 47 | - SOCKET fd; | 43 | + srs_hijack_io_t io; |
| 48 | public: | 44 | public: |
| 49 | SimpleSocketStream(); | 45 | SimpleSocketStream(); |
| 50 | virtual ~SimpleSocketStream(); | 46 | virtual ~SimpleSocketStream(); |
| @@ -49,7 +49,7 @@ using namespace std; | @@ -49,7 +49,7 @@ using namespace std; | ||
| 49 | #include <srs_lib_bandwidth.hpp> | 49 | #include <srs_lib_bandwidth.hpp> |
| 50 | 50 | ||
| 51 | // if want to use your log, define the folowing macro. | 51 | // if want to use your log, define the folowing macro. |
| 52 | -#ifndef SRS_RTMP_USER_DEFINED_LOG | 52 | +#ifndef SRS_HIJACK_LOG |
| 53 | // kernel module. | 53 | // kernel module. |
| 54 | ISrsLog* _srs_log = new ISrsLog(); | 54 | ISrsLog* _srs_log = new ISrsLog(); |
| 55 | ISrsThreadContext* _srs_context = new ISrsThreadContext(); | 55 | ISrsThreadContext* _srs_context = new ISrsThreadContext(); |
| @@ -930,6 +930,93 @@ extern const char* srs_human_format_time(); | @@ -930,6 +930,93 @@ extern const char* srs_human_format_time(); | ||
| 930 | #define srs_human_verbose(msg, ...) printf("[%s] ", srs_human_format_time());printf(msg, ##__VA_ARGS__);printf("\n") | 930 | #define srs_human_verbose(msg, ...) printf("[%s] ", srs_human_format_time());printf(msg, ##__VA_ARGS__);printf("\n") |
| 931 | #define srs_human_raw(msg, ...) printf(msg, ##__VA_ARGS__) | 931 | #define srs_human_raw(msg, ...) printf(msg, ##__VA_ARGS__) |
| 932 | 932 | ||
| 933 | +/************************************************************* | ||
| 934 | +************************************************************** | ||
| 935 | +* IO hijack, use your specified io functions. | ||
| 936 | +************************************************************** | ||
| 937 | +*************************************************************/ | ||
| 938 | +// the void* will convert to your handler for io hijack. | ||
| 939 | +typedef void* srs_hijack_io_t; | ||
| 940 | +// define the following macro and functions in your module to hijack the io. | ||
| 941 | +// the example @see https://github.com/winlinvip/st-load | ||
| 942 | +// which use librtmp but use its own io(use st also). | ||
| 943 | +#ifdef SRS_HIJACK_IO | ||
| 944 | + /** | ||
| 945 | + * create hijack. | ||
| 946 | + * @return NULL for error; otherwise, ok. | ||
| 947 | + */ | ||
| 948 | + extern srs_hijack_io_t srs_hijack_io_create(); | ||
| 949 | + /** | ||
| 950 | + * destroy the context, user must close the socket. | ||
| 951 | + */ | ||
| 952 | + extern void srs_hijack_io_destroy(srs_hijack_io_t ctx); | ||
| 953 | + /** | ||
| 954 | + * create socket, not connect yet. | ||
| 955 | + * @return 0, success; otherswise, failed. | ||
| 956 | + */ | ||
| 957 | + extern int srs_hijack_io_create_socket(srs_hijack_io_t ctx); | ||
| 958 | + /** | ||
| 959 | + * connect socket at server_ip:port. | ||
| 960 | + * @return 0, success; otherswise, failed. | ||
| 961 | + */ | ||
| 962 | + extern int srs_hijack_io_connect(srs_hijack_io_t ctx, const char* server_ip, int port); | ||
| 963 | + /** | ||
| 964 | + * read from socket. | ||
| 965 | + * @return 0, success; otherswise, failed. | ||
| 966 | + */ | ||
| 967 | + extern int srs_hijack_io_read(srs_hijack_io_t ctx, void* buf, size_t size, ssize_t* nread); | ||
| 968 | + /** | ||
| 969 | + * set the socket recv timeout. | ||
| 970 | + * @return 0, success; otherswise, failed. | ||
| 971 | + */ | ||
| 972 | + extern void srs_hijack_io_set_recv_timeout(srs_hijack_io_t ctx, int64_t timeout_us); | ||
| 973 | + /** | ||
| 974 | + * get the socket recv timeout. | ||
| 975 | + * @return 0, success; otherswise, failed. | ||
| 976 | + */ | ||
| 977 | + extern int64_t srs_hijack_io_get_recv_timeout(srs_hijack_io_t ctx); | ||
| 978 | + /** | ||
| 979 | + * get the socket recv bytes. | ||
| 980 | + * @return 0, success; otherswise, failed. | ||
| 981 | + */ | ||
| 982 | + extern int64_t srs_hijack_io_get_recv_bytes(srs_hijack_io_t ctx); | ||
| 983 | + /** | ||
| 984 | + * set the socket send timeout. | ||
| 985 | + * @return 0, success; otherswise, failed. | ||
| 986 | + */ | ||
| 987 | + extern void srs_hijack_io_set_send_timeout(srs_hijack_io_t ctx, int64_t timeout_us); | ||
| 988 | + /** | ||
| 989 | + * get the socket send timeout. | ||
| 990 | + * @return 0, success; otherswise, failed. | ||
| 991 | + */ | ||
| 992 | + extern int64_t srs_hijack_io_get_send_timeout(srs_hijack_io_t ctx); | ||
| 993 | + /** | ||
| 994 | + * get the socket send bytes. | ||
| 995 | + * @return 0, success; otherswise, failed. | ||
| 996 | + */ | ||
| 997 | + extern int64_t srs_hijack_io_get_send_bytes(srs_hijack_io_t ctx); | ||
| 998 | + /** | ||
| 999 | + * writev of socket. | ||
| 1000 | + * @return 0, success; otherswise, failed. | ||
| 1001 | + */ | ||
| 1002 | + extern int srs_hijack_io_writev(srs_hijack_io_t ctx, const iovec *iov, int iov_size, ssize_t* nwrite); | ||
| 1003 | + /** | ||
| 1004 | + * whether the timeout is never timeout. | ||
| 1005 | + * @return 0, success; otherswise, failed. | ||
| 1006 | + */ | ||
| 1007 | + extern bool srs_hijack_io_is_never_timeout(srs_hijack_io_t ctx, int64_t timeout_us); | ||
| 1008 | + /** | ||
| 1009 | + * read fully, fill the buf exactly size bytes. | ||
| 1010 | + * @return 0, success; otherswise, failed. | ||
| 1011 | + */ | ||
| 1012 | + extern int srs_hijack_io_read_fully(srs_hijack_io_t ctx, void* buf, size_t size, ssize_t* nread); | ||
| 1013 | + /** | ||
| 1014 | + * write bytes to socket. | ||
| 1015 | + * @return 0, success; otherswise, failed. | ||
| 1016 | + */ | ||
| 1017 | + extern int srs_hijack_io_write(srs_hijack_io_t ctx, void* buf, size_t size, ssize_t* nwrite); | ||
| 1018 | +#endif | ||
| 1019 | + | ||
| 933 | #ifdef __cplusplus | 1020 | #ifdef __cplusplus |
| 934 | } | 1021 | } |
| 935 | #endif | 1022 | #endif |
-
请 注册 或 登录 后发表评论