src/telnet.c File Reference

#include <stdio.h>
#include <stdlib.h>
#include <gc/gc.h>
#include <stdarg.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <fcntl.h>
#include <time.h>
#include <event.h>
#include <netdb.h>
#include <signal.h>
#include <debug.h>
#include <rbtree.h>
#include "network.h"
#include "telnet.h"
#include "client.h"

Include dependency graph for telnet.c:

Go to the source code of this file.

Defines

#define DEBUG
#define ring_avail(client)
#define ring_char(client, x)   (client->ringbuffer[(client->ringhead+x)%RING_LENGTH])
#define ring_length(client)
#define ring_eat(client, x)   (client->ringhead = (client->ringhead+x) % RING_LENGTH)

Functions

static void telnet_send_req (DESC *client, int how, int request)
static void telnet_send_subop (DESC *client, int how, int option)
static void telnet_handle_will (DESC *client, int option)
static void telnet_handle_wont (DESC *client, int option)
static int telnet_handle_subop (DESC *client, unsigned char *buffer, int length)
int telnet_init (DESC *client)
static void telnet_check_options (DESC *client)
void telnet_read_ring (DESC *client)
void telnet_disconnect (DESC *client)
void telnet_write (DESC *client, char *buffer, int length)


Define Documentation

#define DEBUG

Definition at line 18 of file telnet.c.

#define ring_avail ( client   ) 

Value:

(client->ringtail > client->ringhead ? RING_LENGTH - client->ringtail + client->ringhead : \
        client->ringhead - client->ringtail)

Definition at line 135 of file telnet.c.

Referenced by telnet_read_ring().

#define ring_char ( client,
x   )     (client->ringbuffer[(client->ringhead+x)%RING_LENGTH])

Definition at line 137 of file telnet.c.

Referenced by telnet_read_ring().

#define ring_eat ( client,
x   )     (client->ringhead = (client->ringhead+x) % RING_LENGTH)

Definition at line 140 of file telnet.c.

Referenced by telnet_read_ring().

#define ring_length ( client   ) 

Value:

(client->ringtail >= client->ringhead ? client->ringtail - client->ringhead : \
        RING_LENGTH - client->ringhead + client->ringtail)

Definition at line 138 of file telnet.c.

Referenced by telnet_read_ring().


Function Documentation

static void telnet_check_options ( DESC client  )  [static]

Definition at line 86 of file telnet.c.

References telnet_send_subop().

Referenced by telnet_read_ring().

00087 {
00088         if(client->telnet_has_termtype == TSTATE_SUP) {
00089                 client->telnet_has_termtype = TSTATE_REQUEST;
00090                 telnet_send_subop(client, TELNET_OPT_TERMTYPE, TELNET_SUB_REQUIRED);
00091         } else if(client->telnet_has_termtype == TSTATE_REQUEST) {
00092                 client->telnet_has_termtype = TSTATE_UNSUP;
00093         }
00094 
00095         if(client->telnet_has_winsize == TSTATE_SUP) {
00096                 client->telnet_has_winsize = TSTATE_REQUEST;
00097                 telnet_send_subop(client, TELNET_OPT_WINSIZE, TELNET_SUB_REQUIRED);
00098         } else if(client->telnet_has_winsize == TSTATE_REQUEST) {
00099                 client->telnet_has_termtype = TSTATE_UNSUP;
00100         }
00101 }

void telnet_disconnect ( DESC client  ) 

Definition at line 225 of file telnet.c.

00226 {
00227         network_disconnect(client);
00228 }

static int telnet_handle_subop ( DESC client,
unsigned char *  buffer,
int  length 
) [static]

Definition at line 103 of file telnet.c.

References dprintk.

Referenced by telnet_read_ring().

00105 {
00106         int iter;
00107         if(buffer[1] != TELNET_SUB_SUPPLIED)
00108                 dfail("unexpected reply in telnet suboption negotiation.");
00109         iter = 2;
00110         switch (buffer[0]) {
00111         case TELNET_OPT_TERMTYPE:
00112                 memset(client->termtype, 0, 16);
00113                 for(iter = 2; iter < length && iter < 18 && buffer[iter] != 0xFF;
00114                         iter++) {
00115                         client->termtype[iter - 2] = buffer[iter];
00116                 }
00117                 iter++;
00118                 dprintk("Received Terminal Type '%s'", client->termtype);
00119                 client->telnet_has_termtype = TSTATE_REPLIED;
00120                 break;
00121         case TELNET_OPT_WINSIZE:
00122                 client->telnet_win_width = buffer[2];
00123                 client->telnet_win_height = buffer[4];
00124                 iter = 6;
00125                 dprintk("Received Window Size %dx%d", client->telnet_win_width,
00126                                 client->telnet_win_height);
00127                 client->telnet_has_winsize = TSTATE_REPLIED;
00128                 break;
00129         default:
00130                 dfail("unexpected reply in telnet usboption negotiation.");
00131         }
00132         return iter;
00133 }

static void telnet_handle_will ( DESC client,
int  option 
) [static]

Definition at line 57 of file telnet.c.

References dprintk.

Referenced by telnet_read_ring().

00058 {
00059         switch (option) {
00060         case TELNET_OPT_TERMTYPE:
00061                 client->telnet_has_termtype = TSTATE_SUP;
00062                 dprintk("client acknowledged TERMTYPE");
00063                 break;
00064         case TELNET_OPT_WINSIZE:
00065                 client->telnet_has_winsize = TSTATE_SUP;
00066                 dprintk("client acknowledged WINSIZE");
00067                 break;
00068         }
00069 }

static void telnet_handle_wont ( DESC client,
int  option 
) [static]

Definition at line 71 of file telnet.c.

Referenced by telnet_read_ring().

00072 {
00073         switch (option) {
00074         case TELNET_OPT_TERMTYPE:
00075                 client->telnet_has_termtype = TSTATE_UNSUP;
00076                 strncpy(client->termtype, "vt100", 16);
00077                 break;
00078         case TELNET_OPT_WINSIZE:
00079                 client->telnet_has_winsize = TSTATE_UNSUP;
00080                 client->telnet_win_width = 80;
00081                 client->telnet_win_height = 25;
00082                 break;
00083         }
00084 }

int telnet_init ( DESC client  ) 

Definition at line 32 of file telnet.c.

References dprintk, and telnet_send_req().

Referenced by network_initialize_socket().

00033 {
00034         dprintk("telnet initializing.");
00035         strncpy(client->termtype, "vt100", 16);
00036         client->telnet_win_width = 80;
00037         client->telnet_win_height = 25;
00038 
00039         telnet_send_req(client, TELNET_DO, TELNET_OPT_TERMTYPE);
00040         telnet_send_req(client, TELNET_DO, TELNET_OPT_WINSIZE);
00041         return 1;
00042 }

void telnet_read_ring ( DESC client  ) 

Definition at line 142 of file telnet.c.

References dprintk, ring_avail, ring_char, ring_eat, ring_length, telnet_check_options(), telnet_handle_subop(), telnet_handle_will(), and telnet_handle_wont().

Referenced by network_client_input().

00143 {
00144         int iter, complete;
00145         unsigned char subopt_buffer[32];
00146 
00147         dprintk
00148                 ("Ring Read started, input length = %d, ringhead = %d, ringtail = %d. ",
00149                  ring_length(client), client->ringhead, client->ringtail);
00150 
00151         while (ring_length(client) > 0) {
00152                 dprintk
00153                         ("Parsing data 0x%02x,  %d bytes in ring, ringhead = %d, ringtail = %d",
00154                          ring_char(client, 0), ring_length(client), client->ringhead,
00155                          client->ringtail);
00156                 switch (ring_char(client, 0)) {
00157                 case TELNET_IAC:
00158                         if(ring_length(client) < 2)
00159                                 return;
00160                         dprintk("TELNET COMMADN %d", ring_char(client, 1));
00161                         switch ((unsigned char) ring_char(client, 1)) {
00162                         case TELNET_WILL:
00163                                 telnet_handle_will(client, ring_char(client, 2));
00164                                 ring_eat(client, 3);
00165                                 break;
00166                         case TELNET_WONT:
00167                                 telnet_handle_wont(client, ring_char(client, 2));
00168                                 ring_eat(client, 3);
00169                                 break;
00170                         case TELNET_SB:
00171                                 complete = 0;
00172                                 for(iter = 2; !complete && iter < ring_avail(client); iter++) {
00173                                         subopt_buffer[iter - 2] = ring_char(client, iter);
00174                                         if(ring_char(client, iter) == TELNET_SE) {
00175                                                 telnet_handle_subop(client, subopt_buffer, iter - 2);
00176                                                 complete = 1;
00177                                                 ring_eat(client, iter + 1);
00178                                         }
00179                                 }
00180                                 if(!complete)
00181                                         return;
00182                                 break;
00183                         case TELNET_IAC:
00184                                 client->inputbuffer[client->inputtail++] = TELNET_IAC;
00185                         default:
00186                                 ring_eat(client, 2);
00187                                 break;
00188                         }
00189                         break;
00190                 case 0:
00191                         ring_eat(client, 1);
00192                         break;
00193                 case '\r':
00194                 case '\n':
00195                         if(ring_length(client) > 1 && (ring_char(client, 1) == '\r' ||
00196                                                                                    ring_char(client, 1) == '\n')) {
00197                                 ring_eat(client, 1);
00198                         }
00199                         if(client->inputtail == 0) {
00200                                 ring_eat(client, 1);
00201                                 continue;
00202                         }
00203                         client->inputbuffer[client->inputtail] = 0;
00204                         client_accept_input(client);
00205                         dprintk("Would Parse: %s", client->inputbuffer);
00206                         client->inputtail = 0;
00207                         ring_eat(client, 1);
00208                         break;
00209                 default:
00210                         client->inputbuffer[client->inputtail++] = ring_char(client, 0);
00211                         ring_eat(client, 1);
00212                         break;
00213                 }
00214         }
00215         if(client->ringhead == client->ringtail) {
00216                 client->ringhead = client->ringtail = 0;
00217         }
00218 
00219         telnet_check_options(client);
00220         dprintk
00221                 ("Ring Read finished. RingState = { head = %d, tail = %d }, InputState = { tail = %d }",
00222                  client->ringhead, client->ringtail, client->inputtail);
00223 }

static void telnet_send_req ( DESC client,
int  how,
int  request 
) [static]

Definition at line 45 of file telnet.c.

References network_write().

Referenced by telnet_init().

00046 {
00047         unsigned char buffer[16] = { TELNET_IAC, how, request };
00048         network_write(client, (void *) buffer, 3);
00049 }

static void telnet_send_subop ( DESC client,
int  how,
int  option 
) [static]

Definition at line 50 of file telnet.c.

References network_write().

Referenced by telnet_check_options().

00051 {
00052         unsigned char buffer[16] =
00053                 { TELNET_IAC, TELNET_SB, option, how, TELNET_IAC, TELNET_SE };
00054         network_write(client, (void *) buffer, 6);
00055 }

void telnet_write ( DESC client,
char *  buffer,
int  length 
)

Definition at line 230 of file telnet.c.

References dprintk, and network_write().

00231 {
00232         dprintk("telnet_write");
00233         // Color translation should occur here.
00234         network_write(client, buffer, length);
00235 }


Generated on Mon May 28 04:25:48 2007 for BattletechMUX by  doxygen 1.4.7