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 } |