/**************************************************************************** * apps/examples/rpmsgsocket/rpsock_server.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. The * ASF licenses this file to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include /**************************************************************************** * Private types ****************************************************************************/ struct rpsock_arg_s { int fd; bool nonblock; }; /**************************************************************************** * Public Functions ****************************************************************************/ static void *rpsock_thread(pthread_addr_t pvarg) { struct rpsock_arg_s *args = pvarg; struct pollfd pfd; char buf[255]; ssize_t ret; while (1) { char *tmp; int snd; if (args->nonblock) { memset(&pfd, 0, sizeof(struct pollfd)); pfd.fd = args->fd; pfd.events = POLLIN; ret = poll(&pfd, 1, -1); if (ret < 0) { printf("server poll failed errno %d\n", errno); break; } } ret = recv(args->fd, buf, sizeof(buf), 0); if (ret == 0 || (ret < 0 && errno == ECONNRESET)) { printf("server recv data normal exit\n"); break; } else if (ret < 0 && errno == EAGAIN) { usleep(10); continue; } else if (ret < 0 && errno == EINPROGRESS) { memset(&pfd, 0, sizeof(struct pollfd)); pfd.fd = args->fd; pfd.events = POLLOUT; ret = poll(&pfd, 1, -1); if (ret < 0) { printf("server: poll failure: %d\n", errno); break; } continue; } else if (ret < 0) { printf("server recv data failed ret %zd, errno %d\n", ret, errno); break; } snd = ret; tmp = buf; while (snd > 0) { if (args->nonblock) { memset(&pfd, 0, sizeof(struct pollfd)); pfd.fd = args->fd; pfd.events = POLLOUT; ret = poll(&pfd, 1, -1); if (ret < 0) { printf("server: poll failure: %d\n", errno); break; } } ret = send(args->fd, tmp, snd, 0); if (ret > 0) { tmp += ret; snd -= ret; } else if (ret == 0) { printf("server send data normal exit\n"); break; } else if (errno == EAGAIN) { usleep(10); } else { printf("server send data failed errno %d\n", errno); break; } } } printf("server Complete ret %zd, errno %d\n", ret, errno); free(args); return NULL; } static int rpsock_stream_server(int argc, char *argv[]) { struct sockaddr_rpmsg myaddr; bool nonblock = false; socklen_t addrlen; int listensd; int ret; /* Create a new rpmsg domain socket */ if (strcmp(argv[2], "nonblock") == 0) { nonblock = true; } printf("server: create socket SOCK_STREAM nonblock %d\n", nonblock); if (nonblock) { listensd = socket(PF_RPMSG, SOCK_STREAM | SOCK_NONBLOCK, 0); } else { listensd = socket(PF_RPMSG, SOCK_STREAM, 0); } if (listensd < 0) { printf("server: socket failure: %d\n", errno); return -1; } /* Bind the socket to a local address */ myaddr.rp_family = AF_RPMSG; strlcpy(myaddr.rp_name, argv[3], RPMSG_SOCKET_NAME_SIZE); if (argc == 5) { strlcpy(myaddr.rp_cpu, argv[4], RPMSG_SOCKET_CPU_SIZE); } else { myaddr.rp_cpu[0] = '\0'; } printf("server: bind cpu %s, name %s ...\n", myaddr.rp_cpu, myaddr.rp_name); ret = bind(listensd, (struct sockaddr *)&myaddr, sizeof(myaddr)); if (ret < 0) { printf("server: bind failure: %d\n", errno); goto errout_with_listensd; } /* Listen for connections on the bound socket */ printf("server: listen ...\n"); ret = listen(listensd, 16); if (ret < 0) { printf("server: listen failure %d\n", errno); goto errout_with_listensd; } while (1) { struct rpsock_arg_s *args; pthread_t thread; struct pollfd pfd; int new; if (nonblock) { memset(&pfd, 0, sizeof(struct pollfd)); pfd.fd = listensd; pfd.events = POLLIN; ret = poll(&pfd, 1, -1); if (ret < 0) { printf("server: poll failure: %d\n", errno); goto errout_with_listensd; } } printf("server: try accept ...\n"); new = accept(listensd, (struct sockaddr *)&myaddr, &addrlen); if (new < 0) break; printf("server: Connection accepted -- %d\n", new); args = malloc(sizeof(struct rpsock_arg_s)); assert(args); args->fd = new; args->nonblock = nonblock; pthread_create(&thread, NULL, rpsock_thread, (pthread_addr_t)args); pthread_detach(thread); } printf("server: Terminating\n"); close(listensd); return 0; errout_with_listensd: close(listensd); return -errno; } static int rpsock_dgram_server(int argc, char *argv[]) { struct sockaddr_rpmsg myaddr; struct rpsock_arg_s *args; bool nonblock = false; int fd; int ret; /* Create a new rpmsg domain socket */ if (strcmp(argv[2], "nonblock") == 0) { nonblock = true; } printf("server: create socket SOCK_STREAM nonblock %d\n", nonblock); if (nonblock) { fd = socket(PF_RPMSG, SOCK_DGRAM | SOCK_NONBLOCK, 0); } else { fd = socket(PF_RPMSG, SOCK_DGRAM, 0); } if (fd < 0) { printf("server: socket failure: %d\n", errno); return -errno; } /* Bind the socket to a local address */ myaddr.rp_family = AF_RPMSG; strlcpy(myaddr.rp_name, argv[3], RPMSG_SOCKET_NAME_SIZE); if (argc == 5) { strlcpy(myaddr.rp_cpu, argv[4], RPMSG_SOCKET_CPU_SIZE); } else { myaddr.rp_cpu[0] = '\0'; } printf("server: bind cpu %s, name %s ...\n", myaddr.rp_cpu, myaddr.rp_name); ret = bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)); ret = connect(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)); if (ret < 0 && errno == EINPROGRESS) { struct pollfd pfd; memset(&pfd, 0, sizeof(struct pollfd)); pfd.fd = fd; pfd.events = POLLOUT; ret = poll(&pfd, 1, -1); if (ret < 0) { printf("server: poll failure: %d\n", errno); close(fd); return ret; } } else if (ret < 0) { printf("server: bind failure: %d\n", errno); close(fd); return ret; } args = malloc(sizeof(struct rpsock_arg_s)); assert(args); args->fd = fd; args->nonblock = nonblock; rpsock_thread(args); close(fd); return 0; } int main(int argc, char *argv[]) { if (argc != 4 && argc != 5) { printf("Usage: rpsock_server stream/dgram" " block/nonblock rp_name [rp_cpu]\n"); return -EINVAL; } if (!strcmp(argv[1], "stream")) { return rpsock_stream_server(argc, argv); } else if (!strcmp(argv[1], "dgram")) { return rpsock_dgram_server(argc, argv); } return -EINVAL; }