FreeCalypso > hg > freecalypso-tools
comparison rvinterf/lowlevel/localsock.c @ 0:e7502631a0f9
initial import from freecalypso-sw rev 1033:5ab737ac3ad7
| author | Mychaela Falconia <falcon@freecalypso.org> |
|---|---|
| date | Sat, 11 Jun 2016 00:13:35 +0000 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:e7502631a0f9 |
|---|---|
| 1 /* | |
| 2 * This rvinterf module handles the local UNIX domain socket interface | |
| 3 */ | |
| 4 | |
| 5 #include <sys/types.h> | |
| 6 #include <sys/socket.h> | |
| 7 #include <sys/un.h> | |
| 8 #include <stdio.h> | |
| 9 #include <string.h> | |
| 10 #include <strings.h> | |
| 11 #include <stdlib.h> | |
| 12 #include <unistd.h> | |
| 13 #include "../include/localsock.h" | |
| 14 #include "client.h" | |
| 15 | |
| 16 int listener; | |
| 17 | |
| 18 extern struct client *client_head; | |
| 19 extern int max_fd; | |
| 20 extern char *socket_pathname; | |
| 21 extern int socketpair_fd; | |
| 22 | |
| 23 create_listener_socket() | |
| 24 { | |
| 25 /* local socket binding voodoo copied from osmocon */ | |
| 26 struct sockaddr_un local; | |
| 27 unsigned int namelen; | |
| 28 int rc; | |
| 29 | |
| 30 listener = socket(AF_UNIX, SOCK_STREAM, 0); | |
| 31 if (listener < 0) { | |
| 32 perror("socket(AF_UNIX, SOCK_STREAM, 0)"); | |
| 33 exit(1); | |
| 34 } | |
| 35 | |
| 36 local.sun_family = AF_UNIX; | |
| 37 strncpy(local.sun_path, socket_pathname, sizeof(local.sun_path)); | |
| 38 local.sun_path[sizeof(local.sun_path) - 1] = '\0'; | |
| 39 unlink(local.sun_path); | |
| 40 | |
| 41 /* we use the same magic that X11 uses in Xtranssock.c for | |
| 42 * calculating the proper length of the sockaddr */ | |
| 43 #if defined(BSD44SOCKETS) || defined(__UNIXWARE__) | |
| 44 local.sun_len = strlen(local.sun_path); | |
| 45 #endif | |
| 46 #if defined(BSD44SOCKETS) || defined(SUN_LEN) | |
| 47 namelen = SUN_LEN(&local); | |
| 48 #else | |
| 49 namelen = strlen(local.sun_path) + | |
| 50 offsetof(struct sockaddr_un, sun_path) + 1; | |
| 51 #endif | |
| 52 | |
| 53 rc = bind(listener, (struct sockaddr *) &local, namelen); | |
| 54 if (rc != 0) { | |
| 55 perror("bind on local socket"); | |
| 56 exit(1); | |
| 57 } | |
| 58 rc = listen(listener, 3); | |
| 59 if (rc != 0) { | |
| 60 perror("listen"); | |
| 61 exit(1); | |
| 62 } | |
| 63 | |
| 64 if (listener > max_fd) | |
| 65 max_fd = listener; | |
| 66 return(0); | |
| 67 } | |
| 68 | |
| 69 static void | |
| 70 prep_for_length_rx(cli) | |
| 71 struct client *cli; | |
| 72 { | |
| 73 cli->rx_state = 0; | |
| 74 cli->rx_ptr = cli->rx_buf; | |
| 75 cli->rx_left = 2; | |
| 76 } | |
| 77 | |
| 78 static void | |
| 79 prep_for_message_rx(cli) | |
| 80 struct client *cli; | |
| 81 { | |
| 82 cli->rx_state = 1; | |
| 83 cli->rx_ptr = cli->rx_buf; | |
| 84 cli->rx_left = cli->rx_msglen; | |
| 85 } | |
| 86 | |
| 87 handle_listener_select() | |
| 88 { | |
| 89 struct sockaddr_un un_addr; | |
| 90 socklen_t len; | |
| 91 int rc; | |
| 92 struct client *newcli; | |
| 93 | |
| 94 len = sizeof(un_addr); | |
| 95 rc = accept(listener, (struct sockaddr *) &un_addr, &len); | |
| 96 if (rc < 0) { | |
| 97 perror("rvinterf: accept"); | |
| 98 exit(1); | |
| 99 } | |
| 100 if (rc > max_fd) | |
| 101 max_fd = rc; | |
| 102 newcli = malloc(sizeof(struct client)); | |
| 103 if (!newcli) { | |
| 104 perror("rvinterf: malloc for new client"); | |
| 105 exit(1); | |
| 106 } | |
| 107 bzero(newcli, sizeof(struct client)); | |
| 108 newcli->fd = rc; | |
| 109 newcli->next = client_head; | |
| 110 client_head = newcli; | |
| 111 prep_for_length_rx(newcli); | |
| 112 output_line("*** Client program connected"); | |
| 113 return(0); | |
| 114 } | |
| 115 | |
| 116 create_socketpair_client() | |
| 117 { | |
| 118 struct client *cli; | |
| 119 | |
| 120 if (socketpair_fd > max_fd) | |
| 121 max_fd = socketpair_fd; | |
| 122 cli = malloc(sizeof(struct client)); | |
| 123 if (!cli) { | |
| 124 perror("rvinterf: malloc for socketpair client"); | |
| 125 exit(1); | |
| 126 } | |
| 127 bzero(cli, sizeof(struct client)); | |
| 128 cli->fd = socketpair_fd; | |
| 129 client_head = cli; | |
| 130 prep_for_length_rx(cli); | |
| 131 return(0); | |
| 132 } | |
| 133 | |
| 134 send_local_msg_to_client(cli, msg) | |
| 135 struct client *cli; | |
| 136 char *msg; | |
| 137 { | |
| 138 int len, len1; | |
| 139 u_char hdr[3]; | |
| 140 | |
| 141 len = strlen(msg); | |
| 142 len1 = len + 1; | |
| 143 hdr[0] = len1 >> 8; | |
| 144 hdr[1] = len1 & 0xFF; | |
| 145 hdr[2] = RVI2CLI_LOCAL_CMD_RESP; | |
| 146 write(cli->fd, hdr, 3); | |
| 147 write(cli->fd, msg, len); | |
| 148 } | |
| 149 | |
| 150 void | |
| 151 handle_client_select(cli) | |
| 152 struct client *cli; | |
| 153 { | |
| 154 int cc; | |
| 155 | |
| 156 cc = read(cli->fd, cli->rx_ptr, cli->rx_left); | |
| 157 if (cc <= 0) { | |
| 158 /* normal client exit condition */ | |
| 159 output_line("*** Client program disconnected"); | |
| 160 close_socket: cli->rx_state = 2; | |
| 161 return; | |
| 162 } | |
| 163 cli->rx_ptr += cc; | |
| 164 cli->rx_left -= cc; | |
| 165 if (cli->rx_left) | |
| 166 return; | |
| 167 /* got the thing, process it */ | |
| 168 if (cli->rx_state) { | |
| 169 prep_for_length_rx(cli); | |
| 170 process_msg_from_client(cli); | |
| 171 } else { | |
| 172 cli->rx_msglen = cli->rx_buf[0] << 8 | cli->rx_buf[1]; | |
| 173 if (cli->rx_msglen < 1 || cli->rx_msglen > LOCALSOCK_MAX_MSG) { | |
| 174 send_local_msg_to_client(cli, | |
| 175 "-Invalid length, closing socket"); | |
| 176 goto close_socket; | |
| 177 } | |
| 178 prep_for_message_rx(cli); | |
| 179 } | |
| 180 } |
