Synchronet now requires the libarchive development package (e.g. libarchive-dev on Debian-based Linux distros, libarchive.org for more info) to build successfully.

...
 
Commits (1)
  • Deucе's avatar
    Move telnet expansion/parsing into conn layer · 539408ed
    Deucе authored
    In preperation for telnets support, make conn support TX/RX parsers.
    Make telnet use those new hooks, and remove unused and ambiguous bits
    of the conn API (conn_recv(), conn_peek()).
    539408ed
......@@ -267,38 +267,46 @@ int conn_recv_upto(void *vbuffer, size_t buflen, unsigned timeout)
{
char *buffer = (char *)vbuffer;
size_t found=0;
size_t obuflen;
void *expanded;
size_t max_rx = buflen;
if (conn_api.rx_parse_cb != NULL) {
if (max_rx > 1)
max_rx /= 2;
}
pthread_mutex_lock(&(conn_inbuf.mutex));
if(conn_buf_wait_bytes(&conn_inbuf, 1, timeout))
found=conn_buf_get(&conn_inbuf, buffer, buflen);
found=conn_buf_get(&conn_inbuf, buffer, max_rx);
pthread_mutex_unlock(&(conn_inbuf.mutex));
return(found);
}
int conn_recv(void *vbuffer, size_t buflen, unsigned timeout)
{
char *buffer = (char *)vbuffer;
size_t found;
if (found) {
if (conn_api.rx_parse_cb != NULL) {
expanded = conn_api.rx_parse_cb(buffer, found, &obuflen);
memcpy(vbuffer, expanded, obuflen);
free(expanded);
found = obuflen;
}
else {
expanded = buffer;
obuflen = buflen;
}
}
pthread_mutex_lock(&(conn_inbuf.mutex));
found=conn_buf_wait_bytes(&conn_inbuf, buflen, timeout);
if(found)
found=conn_buf_get(&conn_inbuf, buffer, found);
pthread_mutex_unlock(&(conn_inbuf.mutex));
return(found);
}
int conn_peek(void *vbuffer, size_t buflen)
int conn_send_raw(const void *vbuffer, size_t buflen, unsigned int timeout)
{
char *buffer = (char *)vbuffer;
const char *buffer = vbuffer;
size_t found;
pthread_mutex_lock(&(conn_inbuf.mutex));
found=conn_buf_wait_bytes(&conn_inbuf, buflen, 0);
pthread_mutex_lock(&(conn_outbuf.mutex));
found=conn_buf_wait_free(&conn_outbuf, buflen, timeout);
if(found)
found=conn_buf_peek(&conn_inbuf, buffer, found);
pthread_mutex_unlock(&(conn_inbuf.mutex));
found=conn_buf_put(&conn_outbuf, buffer, found);
pthread_mutex_unlock(&(conn_outbuf.mutex));
return(found);
}
......@@ -306,12 +314,27 @@ int conn_send(const void *vbuffer, size_t buflen, unsigned int timeout)
{
const char *buffer = vbuffer;
size_t found;
size_t obuflen;
void *expanded;
if (conn_api.tx_parse_cb != NULL) {
expanded = conn_api.tx_parse_cb(buffer, buflen, &obuflen);
}
else {
expanded = (void *)buffer;
obuflen = buflen;
}
pthread_mutex_lock(&(conn_outbuf.mutex));
found=conn_buf_wait_free(&conn_outbuf, buflen, timeout);
found=conn_buf_wait_free(&conn_outbuf, obuflen, timeout);
if(found)
found=conn_buf_put(&conn_outbuf, buffer, found);
pthread_mutex_unlock(&(conn_outbuf.mutex));
if (conn_api.tx_parse_cb != NULL) {
free(expanded);
}
return(found);
}
......@@ -321,6 +344,8 @@ int conn_connect(struct bbslist *bbs)
memset(&conn_api, 0, sizeof(conn_api));
conn_api.nostatus = bbs->nostatus;
conn_api.emulation = get_emulation(bbs);
switch(bbs->conn_type) {
case CONN_TYPE_RLOGIN:
case CONN_TYPE_RLOGIN_REVERSED:
......
......@@ -33,8 +33,12 @@ struct conn_api {
int (*close)(void);
void (*binary_mode_on)(void);
void (*binary_mode_off)(void);
void *(*rx_parse_cb)(const void* inbuf, size_t inlen, size_t *olen);
void *(*tx_parse_cb)(const void* inbuf, size_t inlen, size_t *olen);
int log_level;
int type;
int nostatus;
cterm_emulation_t emulation;
volatile int input_thread_running;
volatile int output_thread_running;
volatile int terminate;
......@@ -59,9 +63,8 @@ struct conn_buffer {
* Functions for stuff using connections
*/
int conn_recv_upto(void *buffer, size_t buflen, unsigned int timeout);
int conn_recv(void *buffer, size_t buflen, unsigned int timeout);
int conn_peek(void *buffer, size_t buflen);
int conn_send(const void *buffer, size_t buflen, unsigned int timeout);
int conn_send_raw(const void *buffer, size_t buflen, unsigned int timeout);
int conn_connect(struct bbslist *bbs);
int conn_close(void);
BOOL conn_connected(void);
......
......@@ -15,117 +15,33 @@
#include "uifcinit.h"
#include "telnet_io.h"
#include "rlogin.h"
SOCKET telnet_sock=INVALID_SOCKET;
extern int telnet_log_level;
#ifdef __BORLANDC__
#pragma argsused
#endif
void telnet_input_thread(void *args)
static void *telnet_rx_parse_cb(const void *buf, size_t inlen, size_t *olen)
{
fd_set rds;
int rd;
int buffered;
size_t buffer;
char rbuf[BUFFER_SIZE];
char *buf;
struct bbslist *bbs = args;
SetThreadName("Telnet Input");
conn_api.input_thread_running=1;
while(telnet_sock != INVALID_SOCKET && !conn_api.terminate) {
FD_ZERO(&rds);
FD_SET(telnet_sock, &rds);
#ifdef __linux__
{
struct timeval tv;
tv.tv_sec=0;
tv.tv_usec=500000;
rd=select(telnet_sock+1, &rds, NULL, NULL, &tv);
}
#else
rd=select(telnet_sock+1, &rds, NULL, NULL, NULL);
#endif
if(rd==-1) {
if(errno==EBADF)
break;
rd=0;
}
if(rd==1) {
rd=recv(telnet_sock, conn_api.rd_buf, conn_api.rd_buf_size, 0);
if(rd <= 0)
break;
}
if(rd>0)
buf=(char *)telnet_interpret(conn_api.rd_buf, rd, (BYTE *)rbuf, &rd, bbs);
buffered=0;
while(buffered < rd) {
pthread_mutex_lock(&(conn_inbuf.mutex));
buffer=conn_buf_wait_free(&conn_inbuf, rd-buffered, 100);
buffered+=conn_buf_put(&conn_inbuf, buf+buffered, buffer);
pthread_mutex_unlock(&(conn_inbuf.mutex));
}
}
conn_api.input_thread_running=0;
void *ret = malloc(inlen);
if (ret == NULL)
return ret;
if (telnet_interpret((BYTE *)buf, inlen, ret, olen) != ret)
memcpy(ret, buf, *olen);
return ret;
}
#ifdef __BORLANDC__
#pragma argsused
#endif
void telnet_output_thread(void *args)
static void *telnet_tx_parse_cb(const void *buf, size_t len, size_t *olen)
{
fd_set wds;
size_t wr;
int ret;
size_t sent;
char ebuf[BUFFER_SIZE*2];
char *buf;
SetThreadName("Telnet Output");
conn_api.output_thread_running=1;
while(telnet_sock != INVALID_SOCKET && !conn_api.terminate) {
pthread_mutex_lock(&(conn_outbuf.mutex));
ret=0;
wr=conn_buf_wait_bytes(&conn_outbuf, 1, 100);
if(wr) {
wr=conn_buf_get(&conn_outbuf, conn_api.wr_buf, conn_api.wr_buf_size);
pthread_mutex_unlock(&(conn_outbuf.mutex));
wr = telnet_expand(conn_api.wr_buf, wr, (BYTE *)ebuf, sizeof(ebuf)
,telnet_local_option[TELNET_BINARY_TX]!=TELNET_DO, (uchar**)&buf);
sent=0;
while(sent < wr) {
FD_ZERO(&wds);
FD_SET(telnet_sock, &wds);
#ifdef __linux__
{
struct timeval tv;
tv.tv_sec=0;
tv.tv_usec=500000;
ret=select(telnet_sock+1, NULL, &wds, NULL, &tv);
}
#else
ret=select(telnet_sock+1, NULL, &wds, NULL, NULL);
#endif
if(ret==-1) {
if(errno==EBADF)
break;
ret=0;
}
if(ret==1) {
ret=sendsocket(telnet_sock, buf+sent, wr-sent);
if(ret==-1)
break;
sent+=ret;
}
}
}
else
pthread_mutex_unlock(&(conn_outbuf.mutex));
if(ret==-1)
break;
}
conn_api.output_thread_running=0;
void *ret = malloc(len * 2);
void *parsed;
*olen = telnet_expand(buf, len, ret, len * 2
,telnet_local_option[TELNET_BINARY_TX]!=TELNET_DO, (BYTE **)&parsed);
if (parsed != ret)
memcpy(ret, parsed, *olen);
return ret;
}
int telnet_connect(struct bbslist *bbs)
......@@ -135,8 +51,8 @@ int telnet_connect(struct bbslist *bbs)
telnet_log_level = bbs->telnet_loglevel;
telnet_sock=conn_socket_connect(bbs);
if(telnet_sock==INVALID_SOCKET)
rlogin_sock=conn_socket_connect(bbs);
if(rlogin_sock==INVALID_SOCKET)
return(-1);
if(!create_conn_buf(&conn_inbuf, BUFFER_SIZE))
......@@ -163,9 +79,11 @@ int telnet_connect(struct bbslist *bbs)
memset(telnet_local_option,0,sizeof(telnet_local_option));
memset(telnet_remote_option,0,sizeof(telnet_remote_option));
conn_api.rx_parse_cb = telnet_rx_parse_cb;
conn_api.tx_parse_cb = telnet_tx_parse_cb;
_beginthread(telnet_output_thread, 0, NULL);
_beginthread(telnet_input_thread, 0, bbs);
_beginthread(rlogin_output_thread, 0, NULL);
_beginthread(rlogin_input_thread, 0, bbs);
if (!bbs->hidepopups)
uifc.pop(NULL);
......@@ -173,23 +91,6 @@ int telnet_connect(struct bbslist *bbs)
return(0);
}
int telnet_close(void)
{
char garbage[1024];
conn_api.terminate=1;
closesocket(telnet_sock);
while(conn_api.input_thread_running || conn_api.output_thread_running) {
conn_recv_upto(garbage, sizeof(garbage), 0);
SLEEP(1);
}
destroy_conn_buf(&conn_inbuf);
destroy_conn_buf(&conn_outbuf);
FREE_AND_NULL(conn_api.rd_buf);
FREE_AND_NULL(conn_api.wr_buf);
return(0);
}
void telnet_binary_mode_on(void)
{
request_telnet_opt(TELNET_DO,TELNET_BINARY_TX);
......
......@@ -9,6 +9,6 @@ extern SOCKET telnet_sock;
void telnet_binary_mode_on(void);
void telnet_binary_mode_off(void);
int telnet_connect(struct bbslist *bbs);
int telnet_close(void);
#define telnet_close rlogin_close
#endif
......@@ -10,7 +10,7 @@
#include "conn.h"
#include "uifcinit.h"
static SOCKET sock=INVALID_SOCKET;
SOCKET rlogin_sock=INVALID_SOCKET;
#ifdef __BORLANDC__
#pragma argsused
......@@ -24,18 +24,18 @@ void rlogin_input_thread(void *args)
SetThreadName("RLogin Input");
conn_api.input_thread_running=1;
while(sock != INVALID_SOCKET && !conn_api.terminate) {
while(rlogin_sock != INVALID_SOCKET && !conn_api.terminate) {
FD_ZERO(&rds);
FD_SET(sock, &rds);
FD_SET(rlogin_sock, &rds);
#ifdef __linux__
{
struct timeval tv;
tv.tv_sec=0;
tv.tv_usec=500000;
rd=select(sock+1, &rds, NULL, NULL, &tv);
rd=select(rlogin_sock+1, &rds, NULL, NULL, &tv);
}
#else
rd=select(sock+1, &rds, NULL, NULL, NULL);
rd=select(rlogin_sock+1, &rds, NULL, NULL, NULL);
#endif
if(rd==-1) {
if(errno==EBADF)
......@@ -43,7 +43,7 @@ void rlogin_input_thread(void *args)
rd=0;
}
if(rd==1) {
rd=recv(sock, conn_api.rd_buf, conn_api.rd_buf_size, 0);
rd=recv(rlogin_sock, conn_api.rd_buf, conn_api.rd_buf_size, 0);
if(rd <= 0)
break;
}
......@@ -70,7 +70,7 @@ void rlogin_output_thread(void *args)
SetThreadName("RLogin Output");
conn_api.output_thread_running=1;
while(sock != INVALID_SOCKET && !conn_api.terminate) {
while(rlogin_sock != INVALID_SOCKET && !conn_api.terminate) {
pthread_mutex_lock(&(conn_outbuf.mutex));
ret=0;
wr=conn_buf_wait_bytes(&conn_outbuf, 1, 100);
......@@ -80,16 +80,16 @@ void rlogin_output_thread(void *args)
sent=0;
while(sent < wr) {
FD_ZERO(&wds);
FD_SET(sock, &wds);
FD_SET(rlogin_sock, &wds);
#ifdef __linux__
{
struct timeval tv;
tv.tv_sec=0;
tv.tv_usec=500000;
ret=select(sock+1, NULL, &wds, NULL, &tv);
ret=select(rlogin_sock+1, NULL, &wds, NULL, &tv);
}
#else
ret=select(sock+1, NULL, &wds, NULL, NULL);
ret=select(rlogin_sock+1, NULL, &wds, NULL, NULL);
#endif
if(ret==-1) {
if(errno==EBADF)
......@@ -97,7 +97,7 @@ void rlogin_output_thread(void *args)
ret=0;
}
if(ret==1) {
ret=sendsocket(sock, conn_api.wr_buf+sent, wr-sent);
ret=sendsocket(rlogin_sock, conn_api.wr_buf+sent, wr-sent);
if(ret==-1)
break;
sent+=ret;
......@@ -127,8 +127,8 @@ int rlogin_connect(struct bbslist *bbs)
ruser=bbs->password;
}
sock=conn_socket_connect(bbs);
if(sock==INVALID_SOCKET)
rlogin_sock=conn_socket_connect(bbs);
if(rlogin_sock==INVALID_SOCKET)
return(-1);
if(!create_conn_buf(&conn_inbuf, BUFFER_SIZE))
......@@ -178,17 +178,17 @@ int rlogin_connect(struct bbslist *bbs)
fd_set rds;
FD_ZERO(&rds);
FD_SET(sock, &rds);
FD_SET(rlogin_sock, &rds);
tv.tv_sec=1;
tv.tv_usec=0;
/* Check to make sure GHost is actually listening */
sendsocket(sock, "\r\nMBBS: PING\r\n", 14);
sendsocket(rlogin_sock, "\r\nMBBS: PING\r\n", 14);
idx = 0;
while ((ret = select(sock+1, &rds, NULL, NULL, &tv))==1) {
recv(sock, rbuf+idx, 1, 0);
while ((ret = select(rlogin_sock+1, &rds, NULL, NULL, &tv))==1) {
recv(rlogin_sock, rbuf+idx, 1, 0);
rbuf[++idx] = 0;
/* It says ERROR, but this is a good response to PING. */
......@@ -213,11 +213,11 @@ int rlogin_connect(struct bbslist *bbs)
999, /* Time remaining */
"GR" /* GR = ANSI, NG = ASCII */
);
sendsocket(sock, sbuf, strlen(sbuf));
sendsocket(rlogin_sock, sbuf, strlen(sbuf));
idx = 0;
while ((ret = select(sock+1, &rds, NULL, NULL, &tv))==1) {
recv(sock, rbuf+idx, 1, 0);
while ((ret = select(rlogin_sock+1, &rds, NULL, NULL, &tv))==1) {
recv(rlogin_sock, rbuf+idx, 1, 0);
rbuf[++idx] = 0;
/* GHost says it's launching the program, so pass terminal to user. */
......@@ -252,7 +252,7 @@ int rlogin_close(void)
char garbage[1024];
conn_api.terminate=1;
closesocket(sock);
closesocket(rlogin_sock);
while(conn_api.input_thread_running || conn_api.output_thread_running) {
conn_recv_upto(garbage, sizeof(garbage), 0);
SLEEP(1);
......
......@@ -5,5 +5,8 @@
int rlogin_connect(struct bbslist *bbs);
int rlogin_close(void);
void rlogin_input_thread(void *args);
void rlogin_output_thread(void *args);
extern SOCKET rlogin_sock;
#endif
......@@ -47,35 +47,8 @@ static int lprintf(int level, const char *fmt, ...)
void putcom(char* buf, size_t len)
{
fd_set wds;
FD_ZERO(&wds);
FD_SET(telnet_sock, &wds);
struct timeval tv;
tv.tv_sec=10;
tv.tv_usec=0;
/*
* Note, this select() call was added when debugging file transfer
* issues presumably because something made it appear to "hang forever".
* Since blocking sockets are used, this is very much not a complete
* fix as the buffer size will usually be greater than the one byte
* select() guarantees you will be able to send().
*
* The original fix waited 1ms in select(), which is unlikely to actually
* allow the ACK to come back fast enough to clear a full output buffer.
* I've increased it to 10s and left the select() in place.
*/
if(select(telnet_sock+1, NULL, &wds, NULL, &tv) == 1) {
char str[128];
char* p=str;
size_t i;
for(i=0;i<len;i++)
p+=sprintf(p,"%u ", ((BYTE)buf[i]));
lprintf(LOG_DEBUG,"TX: %s", str);
sendsocket(telnet_sock, buf, len);
} else
lprintf(LOG_WARNING, "TX: putcom(%d) timeout", len);
conn_send_raw(buf, len, 10000);
return;
}
static void send_telnet_cmd(uchar cmd, uchar opt)
......@@ -109,7 +82,7 @@ void request_telnet_opt(uchar cmd, uchar opt)
send_telnet_cmd(cmd,opt);
}
BYTE* telnet_interpret(BYTE* inbuf, int inlen, BYTE* outbuf, int *outlen, struct bbslist *bbs)
BYTE* telnet_interpret(BYTE* inbuf, size_t inlen, BYTE* outbuf, size_t *outlen)
{
BYTE command;
BYTE option;
......@@ -177,7 +150,7 @@ BYTE* telnet_interpret(BYTE* inbuf, int inlen, BYTE* outbuf, int *outlen, struct
/* sub-option terminated */
if(option==TELNET_TERM_TYPE && telnet_cmd[3]==TELNET_TERM_SEND) {
char buf[32];
const char *emu = get_emulation_str(get_emulation(bbs));
const char *emu = get_emulation_str(conn_api.emulation);
int len=sprintf(buf,"%c%c%c%c%s%c%c"
,TELNET_IAC,TELNET_SB
,TELNET_TERM_TYPE,TELNET_TERM_IS
......@@ -220,7 +193,7 @@ BYTE* telnet_interpret(BYTE* inbuf, int inlen, BYTE* outbuf, int *outlen, struct
int rows, cols;
BYTE buf[32];
get_cterm_size(&cols, &rows, bbs->nostatus);
get_cterm_size(&cols, &rows, conn_api.nostatus);
buf[0]=TELNET_IAC;
buf[1]=TELNET_SB;
buf[2]=TELNET_NEGOTIATE_WINDOW_SIZE;
......
......@@ -15,7 +15,7 @@
extern uchar telnet_local_option[0x100];
extern uchar telnet_remote_option[0x100];
BYTE* telnet_interpret(BYTE* inbuf, int inlen, BYTE* outbuf, int *outlen, struct bbslist *bbs);
BYTE* telnet_interpret(BYTE* inbuf, size_t inlen, BYTE* outbuf, size_t *outlen);
void request_telnet_opt(uchar cmd, uchar opt);
#endif