![]() System : Linux absol.cf 5.4.0-198-generic #218-Ubuntu SMP Fri Sep 27 20:18:53 UTC 2024 x86_64 User : www-data ( 33) PHP Version : 7.4.33 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, Directory : /usr/share/emscripten/tests/sockets/ |
Upload File : |
#include <errno.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <sys/ioctl.h> #include <assert.h> #ifdef __EMSCRIPTEN__ #include <emscripten.h> #endif #include "test_sockets_msg.h" // message to send to the server #ifndef MESSAGE #define MESSAGE "pingtothepong" #endif typedef enum { MSG_READ, MSG_WRITE } msg_state_t; typedef struct { int fd; msg_t msg; msg_state_t state; } server_t; server_t server; msg_t echo_msg; int echo_read; int echo_wrote; void finish(int result) { if (server.fd) { close(server.fd); server.fd = 0; } #ifdef __EMSCRIPTEN__ REPORT_RESULT(); emscripten_force_exit(result); #else exit(result); #endif } void main_loop() { static char out[1024*2]; static int pos = 0; fd_set fdr; fd_set fdw; int res; // make sure that server.fd is ready to read / write FD_ZERO(&fdr); FD_ZERO(&fdw); FD_SET(server.fd, &fdr); FD_SET(server.fd, &fdw); res = select(64, &fdr, &fdw, NULL, NULL); if (res == -1) { perror("select failed"); finish(EXIT_FAILURE); } if (server.state == MSG_READ) { if (!FD_ISSET(server.fd, &fdr)) { return; } #if !TEST_DGRAM // as a test, confirm with ioctl that we have data available // after selecting int available; res = ioctl(server.fd, FIONREAD, &available); assert(res != -1); assert(available); #endif res = do_msg_read(server.fd, &server.msg, echo_read, 0, NULL, NULL); if (res == -1) { return; } else if (res == 0) { perror("server closed"); finish(EXIT_FAILURE); } echo_read += res; // once we've read the entire message, validate it if (echo_read >= server.msg.length) { assert(!strcmp(server.msg.buffer, MESSAGE)); finish(EXIT_SUCCESS); } } if (server.state == MSG_WRITE) { if (!FD_ISSET(server.fd, &fdw)) { return; } res = do_msg_write(server.fd, &echo_msg, echo_wrote, 0, NULL, 0); if (res == -1) { return; } else if (res == 0) { perror("server closed"); finish(EXIT_FAILURE); } echo_wrote += res; // once we're done writing the message, read it back if (echo_wrote >= echo_msg.length) { server.state = MSG_READ; } } } // The callbacks for the async network events have a different signature than from // emscripten_set_main_loop (they get passed the fd of the socket triggering the event). // In this test application we want to try and keep as much in common as the timed loop // version but in a real application the fd can be used instead of needing to select(). void async_main_loop(int fd, void* userData) { printf("%s callback\n", userData); main_loop(); } void error_callback(int fd, int err, const char* msg, void* userData) { int error; socklen_t len = sizeof(error); int ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len); printf("%s callback\n", userData); printf("error message: %s\n", msg); if (err == error) { finish(EXIT_SUCCESS); } else { finish(EXIT_FAILURE); } } int main() { struct sockaddr_in addr; int res; memset(&server, 0, sizeof(server_t)); server.state = MSG_WRITE; // setup the message we're going to echo memset(&echo_msg, 0, sizeof(msg_t)); echo_msg.length = strlen(MESSAGE) + 1; echo_msg.buffer = malloc(echo_msg.length); strncpy(echo_msg.buffer, MESSAGE, echo_msg.length); echo_read = 0; echo_wrote = 0; // create the socket and set to non-blocking #if !TEST_DGRAM server.fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); #else server.fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); #endif if (server.fd == -1) { perror("cannot create socket"); finish(EXIT_FAILURE); } fcntl(server.fd, F_SETFL, O_NONBLOCK); // connect the socket memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(SOCKK); if (inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr) != 1) { perror("inet_pton failed"); finish(EXIT_FAILURE); } res = connect(server.fd, (struct sockaddr *)&addr, sizeof(addr)); if (res == -1 && errno != EINPROGRESS) { perror("connect failed"); finish(EXIT_FAILURE); } #ifdef __EMSCRIPTEN__ #if TEST_ASYNC // The first parameter being passed is actually an arbitrary userData pointer // for simplicity this test just passes a basic char* emscripten_set_socket_error_callback("error", error_callback); emscripten_set_socket_open_callback("open", async_main_loop); emscripten_set_socket_message_callback("message", async_main_loop); #else emscripten_set_main_loop(main_loop, 60, 0); #endif #else while (1) main_loop(); #endif return EXIT_SUCCESS; }