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 }