diff --git a/src/syncterm/conn.c b/src/syncterm/conn.c index 06d732c9106ee862a551b6f97f6ccea46e339a97..621f7b43b21b7bd614210a7ee8fd16aa688ad867 100644 --- a/src/syncterm/conn.c +++ b/src/syncterm/conn.c @@ -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: diff --git a/src/syncterm/conn.h b/src/syncterm/conn.h index 5cdc79f76ab1fd8769183e670eb6ee8d82cc554f..f52ae165ca28076321dd125990f29a66d94b0b47 100644 --- a/src/syncterm/conn.h +++ b/src/syncterm/conn.h @@ -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); diff --git a/src/syncterm/conn_telnet.c b/src/syncterm/conn_telnet.c index a1ee81b877faa003184aeae55bca3a7511c2bf9d..224c693518e0f088b52a0d3de81cfafcd512c00e 100644 --- a/src/syncterm/conn_telnet.c +++ b/src/syncterm/conn_telnet.c @@ -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); diff --git a/src/syncterm/conn_telnet.h b/src/syncterm/conn_telnet.h index fa418545ea05fb6e53f54b4bdf123e7f7be10720..71e44092e977051f8d31159c9cec80842745f4d2 100644 --- a/src/syncterm/conn_telnet.h +++ b/src/syncterm/conn_telnet.h @@ -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 diff --git a/src/syncterm/rlogin.c b/src/syncterm/rlogin.c index 5fbb63ea652d8d4451dcc7e9c078596eab7991b1..e7886743240b6f6a175f3d88401ee1454044ed2a 100644 --- a/src/syncterm/rlogin.c +++ b/src/syncterm/rlogin.c @@ -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); diff --git a/src/syncterm/rlogin.h b/src/syncterm/rlogin.h index 80fe28b2ef7788a99d6d7287c59a7be06e46799b..d273da984ac27d2eb123191b0a44fdb2ed9d6223 100644 --- a/src/syncterm/rlogin.h +++ b/src/syncterm/rlogin.h @@ -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 diff --git a/src/syncterm/telnet_io.c b/src/syncterm/telnet_io.c index e11711536da0bbfb25cba9edf8de499048981007..a4b40d3afb62f4620394efb261a4173d5bcd647d 100644 --- a/src/syncterm/telnet_io.c +++ b/src/syncterm/telnet_io.c @@ -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; diff --git a/src/syncterm/telnet_io.h b/src/syncterm/telnet_io.h index 1f10e43c8615dbc359639a5e27d73f566bcaa63e..4ecc5e0e1564ba74e4a7ca55a40f14cfdf5c3cad 100644 --- a/src/syncterm/telnet_io.h +++ b/src/syncterm/telnet_io.h @@ -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