mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
Merge from 4.0release
This commit is contained in:
commit
00395588bc
858 changed files with 216234 additions and 683 deletions
2
trunk/research/msg_zerocopy/.gitignore
vendored
Normal file
2
trunk/research/msg_zerocopy/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
server
|
||||
client
|
16
trunk/research/msg_zerocopy/Makefile
Normal file
16
trunk/research/msg_zerocopy/Makefile
Normal file
|
@ -0,0 +1,16 @@
|
|||
|
||||
.PHONY: default clean
|
||||
|
||||
default: server client
|
||||
|
||||
server: server.cpp ../../objs/st/libst.a
|
||||
g++ -g -O0 -I../../objs/st/ $^ -o $@
|
||||
|
||||
client: client.cpp ../../objs/st/libst.a
|
||||
g++ -g -O0 -I../../objs/st/ $^ -o $@
|
||||
|
||||
../../objs/st/libst.a: ../../Makefile
|
||||
(cd ../../ && $(MAKE) st)
|
||||
|
||||
clean:
|
||||
rm -f server client ../../objs/st/libst.a
|
315
trunk/research/msg_zerocopy/client.cpp
Normal file
315
trunk/research/msg_zerocopy/client.cpp
Normal file
|
@ -0,0 +1,315 @@
|
|||
#include <st.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include <linux/version.h>
|
||||
|
||||
// @see https://www.kernel.org/doc/html/latest/networking/msg_zerocopy.html#notification-reception
|
||||
#include <sys/epoll.h>
|
||||
|
||||
// @see https://github.com/torvalds/linux/blob/master/tools/testing/selftests/net/msg_zerocopy.c
|
||||
#include <linux/errqueue.h>
|
||||
#ifndef SO_EE_ORIGIN_ZEROCOPY
|
||||
#define SO_EE_ORIGIN_ZEROCOPY 5
|
||||
#endif
|
||||
|
||||
#ifndef SO_ZEROCOPY
|
||||
#define SO_ZEROCOPY 60
|
||||
#endif
|
||||
|
||||
#ifndef SO_EE_CODE_ZEROCOPY_COPIED
|
||||
#define SO_EE_CODE_ZEROCOPY_COPIED 1
|
||||
#endif
|
||||
|
||||
#ifndef MSG_ZEROCOPY
|
||||
#define MSG_ZEROCOPY 0x4000000
|
||||
#endif
|
||||
|
||||
#include <netinet/udp.h>
|
||||
// Define macro for UDP GSO.
|
||||
// @see https://github.com/torvalds/linux/blob/master/tools/testing/selftests/net/udpgso.c
|
||||
#ifndef UDP_SEGMENT
|
||||
#define UDP_SEGMENT 103
|
||||
#endif
|
||||
|
||||
void* receiver(void* arg)
|
||||
{
|
||||
st_netfd_t stfd = (st_netfd_t)arg;
|
||||
|
||||
for (;;) {
|
||||
sockaddr_in peer;
|
||||
memset(&peer, 0, sizeof(sockaddr_in));
|
||||
|
||||
char buf[1500];
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
iovec iov;
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = sizeof(buf);
|
||||
|
||||
msghdr msg;
|
||||
memset(&msg, 0, sizeof(msghdr));
|
||||
msg.msg_name = (sockaddr_in*)&peer;
|
||||
msg.msg_namelen = sizeof(sockaddr_in);
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
int r0 = st_recvmsg(stfd, &msg, 0, ST_UTIME_NO_TIMEOUT);
|
||||
assert(r0 > 0);
|
||||
printf("Pong %s:%d %d bytes, flags %#x, %s\n", inet_ntoa(peer.sin_addr), ntohs(peer.sin_port), r0,
|
||||
msg.msg_flags, msg.msg_iov->iov_base);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void parse_reception(st_netfd_t stfd, int nn_confirm)
|
||||
{
|
||||
int left = nn_confirm;
|
||||
while (left > 0) {
|
||||
msghdr msg;
|
||||
memset(&msg, 0, sizeof(msghdr));
|
||||
|
||||
// Reception from kernel, @see https://www.kernel.org/doc/html/latest/networking/msg_zerocopy.html#notification-reception
|
||||
// See do_recv_completion at https://github.com/torvalds/linux/blob/master/tools/testing/selftests/net/msg_zerocopy.c#L393
|
||||
char control[100];
|
||||
msg.msg_control = control;
|
||||
msg.msg_controllen = sizeof(control);
|
||||
// Note that the r0 is 0, the reception is in the control.
|
||||
int r0 = st_recvmsg(stfd, &msg, MSG_ERRQUEUE, ST_UTIME_NO_TIMEOUT);
|
||||
assert(r0 >= 0);
|
||||
assert(msg.msg_flags == MSG_ERRQUEUE);
|
||||
|
||||
// Notification parsing, @see https://www.kernel.org/doc/html/latest/networking/msg_zerocopy.html#notification-parsing
|
||||
cmsghdr* cm = CMSG_FIRSTHDR(&msg);
|
||||
assert(cm->cmsg_level == SOL_IP || cm->cmsg_type == IP_RECVERR);
|
||||
|
||||
sock_extended_err* serr = (sock_extended_err*)(void*)CMSG_DATA(cm);
|
||||
assert(serr->ee_errno == 0 && serr->ee_origin == SO_EE_ORIGIN_ZEROCOPY);
|
||||
|
||||
uint32_t hi = serr->ee_data;
|
||||
uint32_t lo = serr->ee_info;
|
||||
uint32_t range = hi - lo + 1;
|
||||
left -= range;
|
||||
printf("Reception %d bytes, flags %#x, cmsg(level %#x, type %#x), serr(errno %#x, origin %#x, code %#x), range %d [%d, %d]\n",
|
||||
msg.msg_controllen, msg.msg_flags, cm->cmsg_level, cm->cmsg_type, serr->ee_errno, serr->ee_origin, serr->ee_code, range, lo, hi);
|
||||
|
||||
// Defered Copies, @see https://www.kernel.org/doc/html/latest/networking/msg_zerocopy.html#deferred-copies
|
||||
if (serr->ee_code == SO_EE_CODE_ZEROCOPY_COPIED) {
|
||||
printf("Warning: Defered copies, should stop zerocopy\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void usage(int argc, char** argv)
|
||||
{
|
||||
printf("Usage: %s <options>\n", argv[0]);
|
||||
printf("Options:\n");
|
||||
printf(" --help Print this help and exit.\n");
|
||||
printf(" --host=string The host to send to.\n");
|
||||
printf(" --port=int The port to send to.\n");
|
||||
printf(" --pong=bool Whether response pong, true|false\n");
|
||||
printf(" --zerocopy=bool Whether use zerocopy to sendmsg, true|false\n");
|
||||
printf(" --copy=int The copies of message, 1 means sendmmsg(msg+msg)\n");
|
||||
printf(" --loop=int The number of loop to send out messages\n");
|
||||
printf(" --batch=bool Whether read reception by batch, true|false\n");
|
||||
printf(" --mix=bool Whether mix msg with zerocopy and those without, true|false\n");
|
||||
printf(" --size=int Each message size in bytes.\n");
|
||||
printf(" --gso=int The GSO size in bytes, 0 to disable it.\n");
|
||||
printf(" --iovs=int The number of iovs to send, at least 1.\n");
|
||||
printf(" --sndbuf=int The SO_SNDBUF size in bytes, 0 to ignore.\n");
|
||||
printf("For example:\n");
|
||||
printf(" %s --host=127.0.0.1 --port=8000 --pong=true --zerocopy=true --copy=0 --loop=1 --batch=true --mix=true --size=1400 --gso=0 --iovs=1 --sndbuf=0\n", argv[0]);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
option longopts[] = {
|
||||
{ "host", required_argument, NULL, 'o' },
|
||||
{ "port", required_argument, NULL, 'p' },
|
||||
{ "pong", required_argument, NULL, 'n' },
|
||||
{ "zerocopy", required_argument, NULL, 'z' },
|
||||
{ "copy", required_argument, NULL, 'c' },
|
||||
{ "loop", required_argument, NULL, 'l' },
|
||||
{ "batch", required_argument, NULL, 'b' },
|
||||
{ "mix", required_argument, NULL, 'm' },
|
||||
{ "size", required_argument, NULL, 's' },
|
||||
{ "gso", required_argument, NULL, 'g' },
|
||||
{ "iovs", required_argument, NULL, 'i' },
|
||||
{ "sndbuf", required_argument, NULL, 'u' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
char* host = NULL; char ch;
|
||||
int port = 0; int nn_copies = 0; int loop = 1; int size = 1500; int gso = 0; int nn_iovs = 0; int sndbuf = 0;
|
||||
bool pong = false; bool zerocopy = false; bool batch = false; bool mix = false;
|
||||
while ((ch = getopt_long(argc, argv, "o:p:n:z:c:l:b:m:s:g:u:h", longopts, NULL)) != -1) {
|
||||
switch (ch) {
|
||||
case 'o': host = (char*)optarg; break;
|
||||
case 'p': port = atoi(optarg); break;
|
||||
case 'n': pong = !strcmp(optarg,"true"); break;
|
||||
case 'z': zerocopy = !strcmp(optarg,"true"); break;
|
||||
case 'c': nn_copies = atoi(optarg); break;
|
||||
case 'l': loop = atoi(optarg); break;
|
||||
case 'b': batch = !strcmp(optarg,"true"); break;
|
||||
case 'm': mix = !strcmp(optarg,"true"); break;
|
||||
case 's': size = atoi(optarg); break;
|
||||
case 'g': gso = atoi(optarg); break;
|
||||
case 'i': nn_iovs = atoi(optarg); break;
|
||||
case 'u': sndbuf = atoi(optarg); break;
|
||||
case 'h': usage(argc, argv); exit(0);
|
||||
default: usage(argc, argv); exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
printf("Server listen %s:%d, pong %d, zerocopy %d, copies %d, loop %d, batch %d, mix %d, size %d, gso %d, iovs %d, sndbuf %d\n",
|
||||
host, port, pong, zerocopy, nn_copies, loop, batch, mix, size, gso, nn_iovs, sndbuf);
|
||||
if (!host || !port || !nn_iovs) {
|
||||
usage(argc, argv);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
assert(!st_set_eventsys(ST_EVENTSYS_ALT));
|
||||
assert(!st_init());
|
||||
|
||||
int fd = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
assert(fd > 0);
|
||||
|
||||
// @see https://github.com/torvalds/linux/blob/master/tools/testing/selftests/net/msg_zerocopy.c
|
||||
if (zerocopy) {
|
||||
int one = 1;
|
||||
int r0 = setsockopt(fd, SOL_SOCKET, SO_ZEROCOPY, &one, sizeof(one));
|
||||
// MSG_ZEROCOPY for UDP was added in commit b5947e5d1e71 ("udp: msg_zerocopy") in Linux 5.0.
|
||||
// @see https://lore.kernel.org/netdev/CA+FuTSfBFqRViKfG5crEv8xLMgAkp3cZ+yeuELK5TVv61xT=Yw@mail.gmail.com/
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0)
|
||||
if (r0 == -1) {
|
||||
printf("MSG_ZEROCOPY should be kernel 5.0+, kernel %#x, errno=%d\n", LINUX_VERSION_CODE, 524);
|
||||
exit(-1);
|
||||
}
|
||||
#endif
|
||||
assert(!r0);
|
||||
|
||||
printf("epoll events EPOLLERR=%#x, EPOLLHUP=%#x\n", EPOLLERR, EPOLLHUP);
|
||||
}
|
||||
|
||||
if (true) {
|
||||
int dv = 0;
|
||||
socklen_t len = sizeof(dv);
|
||||
int r0 = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &dv, &len);
|
||||
|
||||
int r1 = 0;
|
||||
if (sndbuf > 0) {
|
||||
r1 = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
|
||||
}
|
||||
|
||||
int nv = 0;
|
||||
int r2 = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &nv, &len);
|
||||
printf("socket SO_SNDBUF default=%d, user=%d, now=%d, r0=%d, r1=%d, r2=%d\n", dv, sndbuf, nv, r0, r1, r2);
|
||||
}
|
||||
|
||||
st_netfd_t stfd = st_netfd_open_socket(fd);
|
||||
assert(stfd);
|
||||
printf("Client fd=%d\n", fd);
|
||||
|
||||
if (pong) {
|
||||
st_thread_t r0 = st_thread_create(receiver, stfd, 0, 0);
|
||||
assert(r0);
|
||||
}
|
||||
|
||||
sockaddr_in peer;
|
||||
memset(&peer, 0, sizeof(sockaddr_in));
|
||||
|
||||
peer.sin_family = AF_INET;
|
||||
peer.sin_port = htons(port);
|
||||
peer.sin_addr.s_addr = inet_addr(host);
|
||||
|
||||
char* buf = new char[size];
|
||||
memset(buf, 0, size);
|
||||
memcpy(buf, "Hello", size < 5? size : 5);
|
||||
|
||||
iovec iov;
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = size;
|
||||
|
||||
int nn_confirm = 0;
|
||||
for (int k = 0; k < loop; k++) {
|
||||
msghdr msg;
|
||||
memset(&msg, 0, sizeof(msghdr));
|
||||
msg.msg_name = (sockaddr_in*)&peer;
|
||||
msg.msg_namelen = sizeof(sockaddr_in);
|
||||
msg.msg_iov = new iovec[nn_iovs];
|
||||
msg.msg_iovlen = nn_iovs;
|
||||
|
||||
for (int i = 0; i < nn_iovs; i++) {
|
||||
iovec* p = msg.msg_iov + i;
|
||||
memcpy(p, &iov, sizeof(iovec));
|
||||
}
|
||||
|
||||
if (gso > 0) {
|
||||
msg.msg_controllen = CMSG_SPACE(sizeof(uint16_t));
|
||||
if (!msg.msg_control) {
|
||||
msg.msg_control = new char[msg.msg_controllen];
|
||||
}
|
||||
|
||||
cmsghdr* cm = CMSG_FIRSTHDR(&msg);
|
||||
cm->cmsg_level = SOL_UDP;
|
||||
cm->cmsg_type = UDP_SEGMENT;
|
||||
cm->cmsg_len = CMSG_LEN(sizeof(uint16_t));
|
||||
*((uint16_t*)CMSG_DATA(cm)) = gso;
|
||||
}
|
||||
|
||||
int r0;
|
||||
if (nn_copies == 0) {
|
||||
if (zerocopy) {
|
||||
r0 = st_sendmsg(stfd, &msg, MSG_ZEROCOPY, ST_UTIME_NO_TIMEOUT);
|
||||
} else {
|
||||
r0 = st_sendmsg(stfd, &msg, 0, ST_UTIME_NO_TIMEOUT);
|
||||
}
|
||||
} else {
|
||||
mmsghdr* hdrs = new mmsghdr[nn_copies + 1];
|
||||
for (int i = 0; i < nn_copies + 1; i++) {
|
||||
mmsghdr* p = hdrs + i;
|
||||
memcpy(&p->msg_hdr, &msg, sizeof(msghdr));
|
||||
p->msg_len = 0;
|
||||
}
|
||||
if (zerocopy) {
|
||||
r0 = st_sendmmsg(stfd, hdrs, nn_copies + 1, MSG_ZEROCOPY, ST_UTIME_NO_TIMEOUT);
|
||||
} else {
|
||||
r0 = st_sendmmsg(stfd, hdrs, nn_copies + 1, 0, ST_UTIME_NO_TIMEOUT);
|
||||
}
|
||||
}
|
||||
if (r0 > 0) {
|
||||
printf("Ping %s:%d %d bytes, control %d, copies=%d, r0=%d, %s\n", host, port, iov.iov_len * nn_iovs,
|
||||
msg.msg_controllen, nn_copies, r0, msg.msg_iov->iov_base);
|
||||
} else {
|
||||
printf("Ping %d bytes, error r0=%d, errno=%d\n", iov.iov_len * nn_iovs, r0, errno); exit(1);
|
||||
}
|
||||
|
||||
if (zerocopy && !batch) {
|
||||
parse_reception(stfd, r0);
|
||||
} else {
|
||||
nn_confirm += r0;
|
||||
}
|
||||
|
||||
if (mix) {
|
||||
r0 = st_sendmsg(stfd, &msg, 0, ST_UTIME_NO_TIMEOUT);
|
||||
assert(r0 > 0);
|
||||
printf("Mix %s:%d %d bytes, r0=%d, %s\n", host, port, iov.iov_len * nn_iovs, r0, msg.msg_iov->iov_base);
|
||||
}
|
||||
}
|
||||
|
||||
// @see https://www.kernel.org/doc/html/latest/networking/msg_zerocopy.html#notification-batching
|
||||
if (batch) {
|
||||
parse_reception(stfd, nn_confirm);
|
||||
}
|
||||
|
||||
st_sleep(-1);
|
||||
return 0;
|
||||
}
|
155
trunk/research/msg_zerocopy/server.cpp
Normal file
155
trunk/research/msg_zerocopy/server.cpp
Normal file
|
@ -0,0 +1,155 @@
|
|||
#include <st.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
|
||||
struct message {
|
||||
st_netfd_t stfd;
|
||||
sockaddr_in peer;
|
||||
int delay;
|
||||
};
|
||||
|
||||
void* sender(void* arg)
|
||||
{
|
||||
message* p = (message*)arg;
|
||||
|
||||
int delay = p->delay;
|
||||
if (delay > 0) {
|
||||
st_usleep(delay * 1000);
|
||||
}
|
||||
|
||||
msghdr msg;
|
||||
memset(&msg, 0, sizeof(msghdr));
|
||||
|
||||
sockaddr_in peer = p->peer;
|
||||
msg.msg_name = (sockaddr_in*)&peer;
|
||||
msg.msg_namelen = sizeof(sockaddr_in);
|
||||
|
||||
char buf[] = "World";
|
||||
|
||||
iovec iov;
|
||||
memset(&iov, 0, sizeof(iovec));
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = sizeof(buf);
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
st_netfd_t stfd = p->stfd;
|
||||
int r0 = st_sendmsg(stfd, &msg, 0, ST_UTIME_NO_TIMEOUT);
|
||||
assert(r0 > 0);
|
||||
printf("Pong %s:%d %d bytes, flags %#x, %s\n", inet_ntoa(peer.sin_addr), ntohs(peer.sin_port), r0,
|
||||
msg.msg_flags, msg.msg_iov->iov_base);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void usage(int argc, char** argv)
|
||||
{
|
||||
printf("Usage: %s <options>\n", argv[0]);
|
||||
printf("Options:\n");
|
||||
printf(" --help Print this help and exit.\n");
|
||||
printf(" --host=string The host to send to.\n");
|
||||
printf(" --port=int The port to send to.\n");
|
||||
printf(" --pong=bool Whether response pong, true|false\n");
|
||||
printf(" --delay=int The delay in ms to response pong.\n");
|
||||
printf("For example:\n");
|
||||
printf(" %s --host=0.0.0.0 --port=8000 --pong --delay=100\n", argv[0]);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
option longopts[] = {
|
||||
{ "host", required_argument, NULL, 'o' },
|
||||
{ "port", required_argument, NULL, 'p' },
|
||||
{ "pong", required_argument, NULL, 'n' },
|
||||
{ "delay", required_argument, NULL, 'd' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
char* host = NULL; char ch;
|
||||
int port = 0; int delay = 0; bool pong = false;
|
||||
while ((ch = getopt_long(argc, argv, "o:p:n:d:h", longopts, NULL)) != -1) {
|
||||
switch (ch) {
|
||||
case 'o': host = (char*)optarg; break;
|
||||
case 'p': port = atoi(optarg); break;
|
||||
case 'n': pong = !strcmp(optarg,"true"); break;
|
||||
case 'd': delay = atoi(optarg); break;
|
||||
case 'h': usage(argc, argv); exit(0);
|
||||
default: usage(argc, argv); exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
printf("Server listen %s:%d, pong %d, delay: %dms\n", host, port, pong, delay);
|
||||
if (!host || !port) {
|
||||
usage(argc, argv);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
assert(!st_set_eventsys(ST_EVENTSYS_ALT));
|
||||
assert(!st_init());
|
||||
|
||||
int fd = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
assert(fd > 0);
|
||||
|
||||
int n = 1;
|
||||
int r0 = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&n, sizeof(n));
|
||||
assert(!r0);
|
||||
|
||||
sockaddr_in addr;
|
||||
memset(&addr, 0, sizeof(sockaddr_in));
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
addr.sin_addr.s_addr = inet_addr(host);
|
||||
|
||||
r0 = bind(fd, (sockaddr *)&addr, sizeof(sockaddr_in));
|
||||
assert(!r0);
|
||||
|
||||
st_netfd_t stfd = st_netfd_open_socket(fd);
|
||||
assert(stfd);
|
||||
|
||||
printf("Listen at udp://%s:%d, fd=%d\n", host, port, fd);
|
||||
|
||||
msghdr msg;
|
||||
memset(&msg, 0, sizeof(msghdr));
|
||||
|
||||
sockaddr_in peer;
|
||||
memset(&peer, 0, sizeof(sockaddr_in));
|
||||
msg.msg_name = (sockaddr_in*)&peer;
|
||||
msg.msg_namelen = sizeof(sockaddr_in);
|
||||
|
||||
char buf[1500];
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
iovec iov;
|
||||
memset(&iov, 0, sizeof(iovec));
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = sizeof(buf);
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
int nn_msgs = 0;
|
||||
while (true) {
|
||||
r0 = st_recvmsg(stfd, &msg, 0, ST_UTIME_NO_TIMEOUT);
|
||||
assert(r0 > 0);
|
||||
printf("#%d, From %s:%d %d bytes, flags %#x, %s\n", nn_msgs++, inet_ntoa(peer.sin_addr), ntohs(peer.sin_port),
|
||||
r0, msg.msg_flags, msg.msg_iov->iov_base);
|
||||
|
||||
if (pong) {
|
||||
message* msg = new message();
|
||||
msg->stfd = stfd;
|
||||
msg->peer = peer;
|
||||
msg->delay = delay;
|
||||
st_thread_t r0 = st_thread_create(sender, msg, 0, 0);
|
||||
assert(r0);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
5551
trunk/research/players/js/adapter-7.4.0.js
Normal file
5551
trunk/research/players/js/adapter-7.4.0.js
Normal file
File diff suppressed because it is too large
Load diff
1
trunk/research/players/js/adapter-7.4.0.min.js
vendored
Normal file
1
trunk/research/players/js/adapter-7.4.0.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue