#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 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_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().
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 | ) |
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 }