Raw File
1 #include <sys/socket.h> // for recv...
2 #include <stdlib.h> // for exit...
3 #include <sys/file.h>
4 #include <unistd.h>
5 #include <termios.h>
6 #include <stdio.h>
7 #include <fcntl.h>
8 #include <sys/ioctl.h>
9 #include <pthread.h>
10 #include <sys/select.h>
11
12 #include "util.h"
13 #include "debug.h"
14 #include "dce.h"
15 #include "ip.h"
16 #include "ip232.h"
17
18 void *ip232_thread(void *arg) {
19 dce_config *cfg = (dce_config *)arg;
20 int rc;
21 unsigned char buf[256];
22
23 fd_set readfs;
24 int max_fd = 0;
25
26 LOG_ENTER();
27 for (;;) {
28 FD_ZERO(&readfs);
29 FD_SET(cfg->dp[1][0], &readfs);
30 max_fd = cfg->dp[1][0];
31 FD_SET(cfg->sSocket, &readfs);
32 max_fd = MAX(max_fd, cfg->sSocket);
33 LOG(LOG_ALL, "Waiting for incoming ip232 connections");
34 rc = select(max_fd + 1, &readfs, NULL, NULL, NULL);
35
36 if (rc < 0) {
37 // handle error
38 } else {
39 if (FD_ISSET(cfg->dp[1][0], &readfs)) { // pipe
40 rc = readPipe(cfg->dp[1][0], buf, sizeof(buf) - 1);
41 LOG(LOG_DEBUG, "ip232 thread notified");
42 }
43 if (FD_ISSET(cfg->sSocket, &readfs)) { // ip connection
44 LOG(LOG_DEBUG, "Incoming ip232 connection");
45 rc = ip_accept(cfg->sSocket);
46 if(cfg->is_connected) {
47 LOG(LOG_DEBUG, "Already have ip232 connection, rejecting new");
48 // already have a connection... accept and close
49 if(rc > -1) {
50 close(rc);
51 }
52 } else {
53 if(rc > -1) {
54 cfg->ofd = rc;
55 cfg->ifd = rc;
56 cfg->is_connected = TRUE;
57 cfg->ip232_dtr = FALSE;
58 cfg->ip232_dcd = FALSE;
59 }
60 }
61 }
62 }
63 }
64 LOG_EXIT();
65 }
66
67 int ip232_init_conn(dce_config *cfg) {
68 int rc = -1;
69
70 LOG_ENTER();
71 LOG(LOG_INFO, "Opening ip232 device");
72 if(cfg->tty[0] == '-') { // use STDIN/STDOUT
73 cfg->ofd = STDOUT_FILENO;
74 cfg->ifd = STDIN_FILENO;
75 cfg->is_connected = TRUE;
76 cfg->ip232_dtr = FALSE;
77 cfg->ip232_dcd = FALSE;
78 } else {
79 rc = ip_init_server_conn(cfg->tty, 25232);
80
81 if (rc < 0) {
82 ELOG(LOG_FATAL, "Could not initialize ip232 server socket");
83 exit(-1);
84 }
85 if(-1 == pipe(cfg->dp[0])) {
86 ELOG(LOG_FATAL, "ip232 thread incoming IPC pipe could not be created");
87 exit(-1);
88 }
89
90 if(-1 == pipe(cfg->dp[1])) {
91 ELOG(LOG_FATAL, "ip232 thread outgoing IPC pipe could not be created");
92 exit(-1);
93 }
94
95 cfg->sSocket = rc;
96 cfg->is_connected = FALSE;
97 spawn_thread(ip232_thread, (void *)cfg, "IP232");
98 }
99 LOG(LOG_INFO, "ip232 device configured");
100 LOG_EXIT();
101 return 0;
102 }
103
104
105 int ip232_set_flow_control(dce_config *cfg, int status) {
106 return 0;
107 }
108
109 int ip232_get_control_lines(dce_config *cfg) {
110
111 return ((cfg->is_connected ? DCE_CL_LE : 0)
112 | ((cfg->is_connected && cfg->ip232_dtr) ? DCE_CL_DTR : 0)
113 );
114 }
115
116 int ip232_set_control_lines(dce_config *cfg, int state) {
117 int dcd;
118 int ri;
119 unsigned char cmd[2];
120
121 dcd = (state & DCE_CL_DCD) ? TRUE : FALSE;
122 ri = (state & DCE_CL_RI) ? TRUE : FALSE;
123 LOG(LOG_DEBUG, "ip232 control line state dcd:%x ri:%x", dcd, ri);
124 if ((dcd != cfg->ip232_dcd) || (ri != cfg->ip232_ri)) {
125 LOG(LOG_DEBUG, "reconfiguring virtual DCD/RI");
126 cfg->ip232_dcd = dcd;
127 cfg->ip232_ri = ri;
128 if (cfg->is_connected) {
129 LOG(LOG_DEBUG, "Sending data");
130 cmd[0] = 255;
131 cmd[1] = (dcd ? IP232_DCD : 0) | (ri ? IP232_RI : 0);
132 write(cfg->ofd, cmd, sizeof(cmd));
133 }
134 }
135 return 0;
136 }
137
138 int ip232_write(dce_config *cfg, unsigned char* data, int len) {
139 int retval;
140 int i = 0;
141 int double_iac = FALSE;
142 unsigned char text[1024];
143 int text_len = 0;
144
145 log_trace(TRACE_MODEM_OUT, data, len);
146 retval = len;
147 if (cfg->is_connected) {
148 while(i < len) {
149 if (double_iac) {
150 text[text_len++] = 255;
151 double_iac = FALSE;
152 i++;
153 } else {
154 if(255 == data[i]) {
155 text[text_len++] = 255;
156 double_iac = TRUE;
157 } else {
158 text[text_len++] = data[i++];
159 }
160 }
161
162 if(text_len == sizeof(text)) {
163 retval = write(cfg->ofd, text, text_len);
164 text_len = 0;
165 }
166 }
167 if(text_len) {
168 retval = write(cfg->ofd, text, text_len);
169 }
170 }
171 return retval;
172 }
173
174 int ip232_read(dce_config *cfg, unsigned char *data, int len) {
175 int res;
176 //int rc;
177 unsigned char buf[256];
178 int i = 0;
179 unsigned char ch;
180 int text_len = 0;
181
182 LOG_ENTER();
183 if (len > sizeof(buf)) {
184 LOG(LOG_FATAL, "ip232_read: len > sizeof(buf)");
185 exit(-1);
186 }
187
188 if (cfg->is_connected) {
189 res = recv(cfg->ifd, buf, len, 0);
190 if (0 >= res) {
191 LOG(LOG_INFO, "No ip232 socket data read, assume closed peer");
192 ip_disconnect(cfg->ofd);
193 cfg->is_connected = FALSE;
194 } else {
195 LOG(LOG_DEBUG, "Read %d bytes from ip232 socket", res);
196 log_trace(TRACE_MODEM_IN, buf, res);
197
198 while(i < res) {
199 ch = buf[i];
200 if (cfg->ip232_iac) {
201 cfg->ip232_iac = FALSE;
202 switch (ch) {
203 case 0:
204 cfg->ip232_dtr = FALSE;
205 LOG(LOG_DEBUG, "Virtual DTR line down");
206 break;
207 case 1:
208 cfg->ip232_dtr = TRUE;
209 LOG(LOG_DEBUG, "Virtual DTR line up");
210 break;
211 case 255:
212 data[text_len++] = 255;
213 break;
214 }
215 } else {
216 if (255 == ch) {
217 cfg->ip232_iac = TRUE;
218 } else {
219 data[text_len++] = ch;
220 }
221 }
222 i++;
223 }
224 }
225 }
226 LOG_EXIT();
227 return text_len;
228 }
229
Generated by GNU Enscript 1.6.6, and GophHub 1.3.