17 mud_connect(const char *name
,
20 size_t in_bufsz
, size_t out_bufsz
, int fd
)
23 struct sockaddr_in sin
;
25 struct addrinfo ai_hint
;
28 memset(&ai_hint
, 0, sizeof(ai_hint
));
31 mud
= malloc (sizeof(*mud
));
34 memset(mud
, 0, sizeof(*mud
));
35 mud
->input_buffer
= malloc(in_bufsz
);
36 mud
->output_buffer
= malloc(out_bufsz
);
37 if (!mud
->input_buffer
|| !mud
->output_buffer
) {
41 mud
->input_buffer
= cb_init(mud
->input_buffer
, in_bufsz
, NULL
);
42 mud
->output_buffer
= cb_init(mud
->output_buffer
, out_bufsz
, NULL
);
43 mud
->name
= strdup(name
);
44 mud
->host
= strdup(host
);
51 mud
->sockfd
= socket(PF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
52 if (mud
->sockfd
< 0) {
53 fprintf(stderr
, "socket: %s\n", strerror(errno
));
57 memset(&ai_hint
,0, sizeof(ai_hint
));
58 ai_hint
.ai_family
= PF_INET
;
59 ret
= getaddrinfo(host
, NULL
, &ai_hint
, &ai
);
61 fprintf(stderr
, "getaddrinfo: %s\n", gai_strerror(ret
));
65 memcpy(&sin
, ai
->ai_addr
, sizeof(sin
));
66 sin
.sin_family
= PF_INET
;
67 sin
.sin_port
= htons(port
);
71 if (connect(mud
->sockfd
, (struct sockaddr
*)&sin
,
72 (socklen_t
)(sizeof(sin
))) < 0) {
73 fprintf(stderr
, "connect: %s\n", strerror(errno
));
86 cb_free(mud
->input_buffer
);
87 cb_free(mud
->output_buffer
);
95 mud_create(const char *name
,
98 size_t in_bufsz
, size_t out_bufsz
)
100 return mud_connect(name
, host
, port
, in_bufsz
, out_bufsz
, -1);
106 do_telnet_req(mud_conn_t
*mud
, buf
[x
]);
113 telnet_scan_buf(mud_conn_t
*mud
, char *buf
, size_t len
, size_t curr
)
121 for (x
= 0; x
< curr
; x
++) {
125 if (req
&& in_code
== 2) {
126 do_req(mud
, req
, buf
[x
]);
157 delta_est(struct timeval
*old
, struct timeval
*now
)
161 if (now
->tv_usec
> old
->tv_usec
) {
162 old
->tv_usec
+= 1000000;
165 tv
.tv_sec
= now
->tv_sec
- old
->tv_sec
;
166 tv
.tv_usec
= now
->tv_usec
- old
->tv_usec
;
168 return ((tv
.tv_sec
* 1000) + (tv
.tv_usec
/ 1000));
173 est_rtt(mud_conn_t
*mud
, struct timeval
*prev
, struct timeval
*now
)
176 mud
->rtt_hist
[mud
->rtt_idx
] = delta_est(prev
, now
);
178 if (mud
->rtt_idx
>= RTT_HIST_LEN
)
181 for (x
= 0; x
< RTT_HIST_LEN
; x
++) {
182 if (mud
->rtt_hist
[x
] == 0)
184 total
+= mud
->rtt_hist
[x
];
187 mud
->rtt
= (total
/ x
);
192 mud_io(mud_conn_t
*mud
)
194 char buf
[4096]; // XXX _sysconf(_SC_PAGESIZE)
196 int ret
, total
= 0, timeout
= 0, written
= 0;
202 memset(&fd
, 0, sizeof(fd
));
204 fd
.events
= POLLIN
| POLLERR
| POLLHUP
;
206 if (cb_length(mud
->output_buffer
))
207 fd
.events
|= POLLOUT
;
209 switch (poll(&fd
, 1, timeout
)) {
218 if (fd
.revents
& (POLLERR
|POLLHUP
)) {
222 if ((fd
.revents
& POLLOUT
) && cb_length(mud
->output_buffer
)) {
223 written
= write(mud
->sockfd
,
225 cb_length(mud
->output_buffer
));
227 gettimeofday(&mud
->last_send
, NULL
);
228 cb_discard(mud
->output_buffer
, (size_t)written
);
232 if (!(fd
.revents
& POLLIN
))
236 ret
= read(mud
->sockfd
,
246 //telnet_scan_buf(mud, buf, sizeof(buf), ret);
249 if (!written
&& mud
->last_send
.tv_sec
) {
250 gettimeofday(&tv
, NULL
);
251 est_rtt(mud
, &mud
->last_send
, &tv
);
252 mud
->last_send
.tv_sec
= 0;
254 cb_append(mud
->input_buffer
, buf
, ret
);
258 if (total
== 0 && ret
== 0)
259 /* went high but no data? lost conn (only on some systems) */
261 } while (ret
== sizeof(buf
));
266 if (mud
->sockfd
>= 0)
269 cb_strcat(mud
->input_buffer
, "\n\nNO CARRIER\n");